aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml87
-rw-r--r--doc/qbs.qdoc30
-rw-r--r--doc/reference/cli/cli-options.qdocinc1
-rw-r--r--doc/reference/commands.qdoc9
-rw-r--r--examples/baremetal/at90can128olimex/redblink/redblink.qbs2
-rw-r--r--examples/baremetal/baremetal.qbs3
-rw-r--r--examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs5
-rw-r--r--examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs2
-rw-r--r--examples/baremetal/stm8s103f3/redblink/README.md8
-rw-r--r--examples/baremetal/stm8s103f3/redblink/gpio.c68
-rw-r--r--examples/baremetal/stm8s103f3/redblink/gpio.h65
-rw-r--r--examples/baremetal/stm8s103f3/redblink/main.c69
-rw-r--r--examples/baremetal/stm8s103f3/redblink/redblink.qbs111
-rw-r--r--examples/baremetal/stm8s103f3/redblink/system.h84
-rw-r--r--examples/baremetal/stm8s103f3/stm8s103f3.qbs58
-rw-r--r--examples/collidingmice/collidingmice.qbs4
-rwxr-xr-xscripts/build-qbs-with-qbs.sh27
-rw-r--r--share/qbs/imports/qbs/Probes/IarProbe.qbs4
-rw-r--r--share/qbs/imports/qbs/base/AutotestRunner.qbs6
-rw-r--r--share/qbs/modules/autotest/autotest.qbs1
-rw-r--r--share/qbs/modules/cpp/iar.js35
-rw-r--r--share/qbs/modules/cpp/iar.qbs18
-rw-r--r--share/qbs/modules/cpp/sdcc.js12
-rw-r--r--share/qbs/modules/cpp/sdcc.qbs4
-rw-r--r--src/app/qbs-setup-toolchains/clangclprobe.cpp18
-rw-r--r--src/app/qbs-setup-toolchains/clangclprobe.h14
-rw-r--r--src/app/qbs-setup-toolchains/commandlineparser.h3
-rw-r--r--src/app/qbs-setup-toolchains/gccprobe.cpp477
-rw-r--r--src/app/qbs-setup-toolchains/gccprobe.h62
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.cpp102
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.h12
-rw-r--r--src/app/qbs-setup-toolchains/keilprobe.cpp124
-rw-r--r--src/app/qbs-setup-toolchains/keilprobe.h12
-rw-r--r--src/app/qbs-setup-toolchains/msvcprobe.cpp5
-rw-r--r--src/app/qbs-setup-toolchains/msvcprobe.h14
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp347
-rw-r--r--src/app/qbs-setup-toolchains/probe.h32
-rw-r--r--src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro2
-rw-r--r--src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs2
-rw-r--r--src/app/qbs-setup-toolchains/sdccprobe.cpp161
-rw-r--r--src/app/qbs-setup-toolchains/sdccprobe.h12
-rw-r--r--src/app/qbs-setup-toolchains/xcodeprobe.h6
-rw-r--r--src/lib/corelib/buildgraph/abstractcommandexecutor.cpp21
-rw-r--r--src/lib/corelib/buildgraph/abstractcommandexecutor.h9
-rw-r--r--src/lib/corelib/buildgraph/jscommandexecutor.cpp16
-rw-r--r--src/lib/corelib/buildgraph/jscommandexecutor.h5
-rw-r--r--src/lib/corelib/buildgraph/processcommandexecutor.cpp26
-rw-r--r--src/lib/corelib/buildgraph/processcommandexecutor.h6
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.cpp14
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.h6
-rw-r--r--src/lib/corelib/corelib.qbs17
-rw-r--r--src/lib/corelib/generators/generators.pri22
-rw-r--r--src/lib/corelib/generators/generatorutils.cpp213
-rw-r--r--src/lib/corelib/generators/generatorutils.h91
-rw-r--r--src/lib/corelib/generators/generatorversioninfo.cpp83
-rw-r--r--src/lib/corelib/generators/generatorversioninfo.h78
-rw-r--r--src/lib/corelib/generators/ixmlnodevisitor.h69
-rw-r--r--src/lib/corelib/generators/xmlproject.cpp50
-rw-r--r--src/lib/corelib/generators/xmlproject.h54
-rw-r--r--src/lib/corelib/generators/xmlprojectwriter.cpp92
-rw-r--r--src/lib/corelib/generators/xmlprojectwriter.h70
-rw-r--r--src/lib/corelib/generators/xmlproperty.cpp56
-rw-r--r--src/lib/corelib/generators/xmlproperty.h88
-rw-r--r--src/lib/corelib/generators/xmlpropertygroup.cpp67
-rw-r--r--src/lib/corelib/generators/xmlpropertygroup.h78
-rw-r--r--src/lib/corelib/generators/xmlworkspace.cpp66
-rw-r--r--src/lib/corelib/generators/xmlworkspace.h69
-rw-r--r--src/lib/corelib/generators/xmlworkspacewriter.cpp92
-rw-r--r--src/lib/corelib/generators/xmlworkspacewriter.h70
-rw-r--r--src/lib/corelib/tools/version.cpp12
-rw-r--r--src/lib/corelib/tools/version.h4
-rw-r--r--src/plugins/generator/generator.pro6
-rw-r--r--src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp95
-rw-r--r--src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h58
-rw-r--r--src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp230
-rw-r--r--src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h63
-rw-r--r--src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp98
-rw-r--r--src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h71
-rw-r--r--src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp478
-rw-r--r--src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h63
-rw-r--r--src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp551
-rw-r--r--src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h63
-rw-r--r--src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp489
-rw-r--r--src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h71
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp94
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h58
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp226
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h61
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp98
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h72
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp492
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h64
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp774
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h63
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp388
-rw-r--r--src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h66
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp95
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h59
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp228
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h62
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp98
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h71
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp476
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h65
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp1014
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h66
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp336
-rw-r--r--src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h68
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp94
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h59
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp229
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h62
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp98
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h72
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp442
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h65
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp366
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h64
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp411
-rw-r--r--src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h73
-rw-r--r--src/plugins/generator/iarew/iarew.pro115
-rw-r--r--src/plugins/generator/iarew/iarew.qbs114
-rw-r--r--src/plugins/generator/iarew/iarewfileversionproperty.cpp54
-rw-r--r--src/plugins/generator/iarew/iarewfileversionproperty.h49
-rw-r--r--src/plugins/generator/iarew/iarewgenerator.cpp158
-rw-r--r--src/plugins/generator/iarew/iarewgenerator.h70
-rw-r--r--src/plugins/generator/iarew/iarewgeneratorplugin.cpp67
-rw-r--r--src/plugins/generator/iarew/iarewoptionpropertygroup.cpp58
-rw-r--r--src/plugins/generator/iarew/iarewoptionpropertygroup.h51
-rw-r--r--src/plugins/generator/iarew/iarewproject.cpp127
-rw-r--r--src/plugins/generator/iarew/iarewproject.h56
-rw-r--r--src/plugins/generator/iarew/iarewprojectwriter.cpp52
-rw-r--r--src/plugins/generator/iarew/iarewprojectwriter.h51
-rw-r--r--src/plugins/generator/iarew/iarewsettingspropertygroup.cpp106
-rw-r--r--src/plugins/generator/iarew/iarewsettingspropertygroup.h68
-rw-r--r--src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp54
-rw-r--r--src/plugins/generator/iarew/iarewsourcefilepropertygroup.h52
-rw-r--r--src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp56
-rw-r--r--src/plugins/generator/iarew/iarewsourcefilespropertygroup.h50
-rw-r--r--src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp43
-rw-r--r--src/plugins/generator/iarew/iarewtoolchainpropertygroup.h48
-rw-r--r--src/plugins/generator/iarew/iarewutils.cpp156
-rw-r--r--src/plugins/generator/iarew/iarewutils.h75
-rw-r--r--src/plugins/generator/iarew/iarewversioninfo.cpp76
-rw-r--r--src/plugins/generator/iarew/iarewversioninfo.h61
-rw-r--r--src/plugins/generator/iarew/iarewworkspace.cpp63
-rw-r--r--src/plugins/generator/iarew/iarewworkspace.h58
-rw-r--r--src/plugins/generator/iarew/iarewworkspacewriter.cpp52
-rw-r--r--src/plugins/generator/iarew/iarewworkspacewriter.h51
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp109
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h70
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp50
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp50
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp50
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp143
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp140
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp281
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp56
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp240
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp104
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp50
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h54
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp83
-rw-r--r--src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h67
-rw-r--r--src/plugins/generator/keiluv/keiluv.pro63
-rw-r--r--src/plugins/generator/keiluv/keiluv.qbs62
-rw-r--r--src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp197
-rw-r--r--src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h52
-rw-r--r--src/plugins/generator/keiluv/keiluvgenerator.cpp159
-rw-r--r--src/plugins/generator/keiluv/keiluvgenerator.h71
-rw-r--r--src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp67
-rw-r--r--src/plugins/generator/keiluv/keiluvproject.cpp111
-rw-r--r--src/plugins/generator/keiluv/keiluvproject.h58
-rw-r--r--src/plugins/generator/keiluv/keiluvprojectwriter.cpp58
-rw-r--r--src/plugins/generator/keiluv/keiluvprojectwriter.h51
-rw-r--r--src/plugins/generator/keiluv/keiluvutils.cpp123
-rw-r--r--src/plugins/generator/keiluv/keiluvutils.h64
-rw-r--r--src/plugins/generator/keiluv/keiluvversioninfo.cpp76
-rw-r--r--src/plugins/generator/keiluv/keiluvversioninfo.h61
-rw-r--r--src/plugins/generator/keiluv/keiluvworkspace.cpp68
-rw-r--r--src/plugins/generator/keiluv/keiluvworkspace.h56
-rw-r--r--src/plugins/generator/keiluv/keiluvworkspacewriter.cpp58
-rw-r--r--src/plugins/generator/keiluv/keiluvworkspacewriter.h51
-rw-r--r--src/plugins/plugins.qbs2
-rw-r--r--tests/auto/api/testdata/timeout-js/timeout.qbs20
-rw-r--r--tests/auto/api/testdata/timeout-process/main.cpp37
-rw-r--r--tests/auto/api/testdata/timeout-process/timeout.qbs24
-rw-r--r--tests/auto/api/tst_api.cpp64
-rw-r--r--tests/auto/api/tst_api.h3
-rw-r--r--tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs2
-rw-r--r--tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp2
-rw-r--r--tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs9
-rw-r--r--tests/auto/blackbox/testdata/autotest-timeout/test-main.cpp37
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp29
-rw-r--r--tests/auto/blackbox/tst_blackbox.h3
-rw-r--r--tests/auto/blackbox/tst_blackboxjoblimits.cpp2
205 files changed, 18609 insertions, 382 deletions
diff --git a/.travis.yml b/.travis.yml
index cead59a79..acb1730d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,3 +29,90 @@ jobs:
name: With QMake on Debian stretch (linux_amd64)
script:
- docker-compose run --rm ${SERVICE} scripts/build-qbs-with-qmake.sh
+
+ - &build-on-macos
+ stage: Build Qbs and and run autotests
+ name: With Qbs on macOS (xcode 10.2)
+ os: osx
+ osx_image: xcode10.2
+ addons:
+ homebrew:
+ packages:
+ - p7zip
+ update: true
+ env:
+ # Address sanitizer slows autotests down too much.
+ # We would hit the maximum build time on Travis.
+ BUILD_OPTIONS=modules.qbsbuildconfig.enableAddressSanitizer:false
+ QT_INSTALL_DIR=/Users/travis/Qt
+ QMAKE_PATH=${QT_INSTALL_DIR}/5.12.4/clang_64/bin/qmake
+ PATH="${QT_INSTALL_DIR}/Qt Creator.app/Contents/MacOS:${PATH}"
+ QBS_BUILD_PROFILE=qt
+ before_install:
+ - curl -L -o qtbase.7z http://master.qt.io/online/qtsdkrepository/mac_x64/desktop/qt5_5124/qt.qt5.5124.clang_64/5.12.4-0-201906140148qtbase-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64.7z
+ - curl -L -o qtdeclarative.7z http://master.qt.io/online/qtsdkrepository/mac_x64/desktop/qt5_5124/qt.qt5.5124.clang_64/5.12.4-0-201906140148qtdeclarative-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64.7z
+ - curl -L -o qttools.7z http://master.qt.io/online/qtsdkrepository/mac_x64/desktop/qt5_5124/qt.qt5.5124.clang_64/5.12.4-0-201906140148qttools-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64.7z
+ - curl -L -o qtscript.7z http://master.qt.io/online/qtsdkrepository/mac_x64/desktop/qt5_5124/qt.qt5.5124.qtscript.clang_64/5.12.4-0-201906140148qtscript-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64.7z
+ - curl -L -o qtcreator.7z http://master.qt.io/online/qtsdkrepository/mac_x64/desktop/tools_qtcreator/qt.tools.qtcreator/4.9.1-0qtcreator.7z
+ - 7z x -o${QT_INSTALL_DIR} qtbase.7z
+ - 7z x -o${QT_INSTALL_DIR} qtdeclarative.7z
+ - 7z x -o${QT_INSTALL_DIR} qttools.7z
+ - 7z x -o${QT_INSTALL_DIR} qtscript.7z
+ - 7z x -o${QT_INSTALL_DIR} qtcreator.7z
+ - printf "[Paths]\nPrefix = ..\n" > ${QT_INSTALL_DIR}/5.12.4/clang_64/bin/qt.conf
+ - pip2 install --user beautifulsoup4 lxml
+ script:
+ - qbs setup-toolchains --detect
+ - qbs setup-qt ${QMAKE_PATH} qt
+ - qbs config qt.baseProfile xcode-macosx-x86_64
+ - qbs config defaultProfile qt
+ - scripts/build-qbs-with-qbs.sh
+
+# Disabled because of https://bugreports.qt.io/browse/QBS-1456
+# - <<: *build-on-macos
+# name: With Qbs on macOS (xcode 9.4)
+# osx_image: xcode9.4
+
+ - &build-on-windows
+ stage: Build Qbs and and run autotests
+ name: With Qbs on Windows (Visual Studio 2017)
+ os: windows
+ env:
+ # Need to build in release mode. Otherwise autotests would be too slow.
+ BUILD_OPTIONS="config:release"
+ QT_INSTALL_DIR=C:/Qt
+ QMAKE_PATH=${QT_INSTALL_DIR}/5.12.4/msvc2017_64/bin/qmake.exe
+ PATH="/c/Qt/Tools/QtCreator/bin:${PATH}"
+ WITH_DOCS=0
+ QBS_BUILD_PROFILE=qt
+ before_install:
+ # Disable unnecessary background services which tend to consume
+ # a lot of resources
+ - powershell -Command 'Set-MpPreference -DisableRealtimeMonitoring $true'
+ - powershell -Command 'Set-MpPreference -DisableArchiveScanning $true'
+ - powershell -Command 'Set-MpPreference -DisableBehaviorMonitoring $true'
+ - powershell -Command 'sc.exe config TrustedInstaller start=disabled; sc.exe stop TrustedInstaller'
+ - powershell -Command 'sc.exe config wuauserv start=disabled; sc.exe stop wuauserv'
+ - powershell -Command 'Add-MpPreference -ExclusionPath C:\'
+ - powershell -Command 'Add-MpPreference -ExclusionProcess qbs.exe'
+ - powershell -Command 'Add-MpPreference -ExclusionProcess cl.exe'
+ - powershell -Command 'Add-MpPreference -ExclusionProcess link.exe'
+
+ # Install Qbs and Qt
+ - curl -L -o qtbase.7z http://master.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5124/qt.qt5.5124.win64_msvc2017_64/5.12.4-0-201906140149qtbase-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z
+ - curl -L -o qtdeclarative.7z http://master.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5124/qt.qt5.5124.win64_msvc2017_64/5.12.4-0-201906140149qtdeclarative-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z
+ - curl -L -o qttools.7z http://master.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5124/qt.qt5.5124.win64_msvc2017_64/5.12.4-0-201906140149qttools-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z
+ - curl -L -o qtscript.7z http://master.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5124/qt.qt5.5124.qtscript.win64_msvc2017_64/5.12.4-0-201906140149qtscript-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z
+ - curl -L -o qtcreator.7z http://master.qt.io/online/qtsdkrepository/windows_x86/desktop/tools_qtcreator/qt.tools.qtcreator/4.9.2-0qtcreator.7z
+ - 7z x -o${QT_INSTALL_DIR} qtbase.7z
+ - 7z x -o${QT_INSTALL_DIR} qtdeclarative.7z
+ - 7z x -o${QT_INSTALL_DIR} qttools.7z
+ - 7z x -o${QT_INSTALL_DIR} qtscript.7z
+ - 7z x -o${QT_INSTALL_DIR} qtcreator.7z
+ - echo -e "[Paths]\nPrefix = .." > $(dirname ${QMAKE_PATH})/qt.conf
+ script:
+ - qbs setup-toolchains --detect
+ - qbs setup-qt ${QMAKE_PATH} qt
+ - qbs config qt.baseProfile MSVC2017-x86
+ - qbs config defaultProfile qt
+ - scripts/build-qbs-with-qbs.sh
diff --git a/doc/qbs.qdoc b/doc/qbs.qdoc
index d2c703491..3ab42314e 100644
--- a/doc/qbs.qdoc
+++ b/doc/qbs.qdoc
@@ -1721,7 +1721,7 @@
integrate \QBS with popular IDEs, such as Microsoft Visual Studio, and to
generate Clang compilation databases.
- \section1 Generating Projects
+ \section1 Generating Microsoft Visual Studio Projects
To generate a project for another build system, such as Microsoft Visual
Studio, use the \l{generate}{qbs generate} command and specify a generator
@@ -1744,6 +1744,34 @@
\l{generate}{qbs generate} in order for the changes to be reflected in your
IDE.
+ \section1 Generating IAR Embedded Workbench Projects
+
+ To generate a project for an \l{https://www.iar.com/iar-embedded-workbench/}
+ {IAR Embedded Workbench}, use the \l{generate}{qbs generate} command and specify
+ a generator using the \l{generate-generator}{-g} option. For example:
+
+ \code
+ # For IAREW v8xxxx
+ qbs generate -g iarew8 profile:<your/qbs/profile>
+ qbs generate -g iarew8 -d <path/to/build/directory> -f <path/to/qbs/project> profile:<your/qbs/profile>
+ \endcode
+
+ \note You need to specify a specific QBS profile, which is required for a generator
+ to fetch a target architecture to generate the project.
+
+ \note An existing IAR EW generator creates a native target project for a specified
+ IAR Embedded Workbench.
+
+ Supported IAR EW generators are listed in a table below:
+
+ \table
+ \header \li Generator \li IAR EW Version \li Target Architecture
+ \row \li iarew8 \li All 8.x.y versions \li ARM
+ \row \li iarew7 \li All 7.x.y versions \li AVR
+ \row \li iarew10 \li All 10.x.y versions \li 8051 (aka MCS51)
+ \row \li iarew3 \li All 3.x.y versions \li STM8
+ \endtable
+
\section1 Generating Clang Compilation Databases
To generate a \l{JSON Compilation Database Format Specification}
diff --git a/doc/reference/cli/cli-options.qdocinc b/doc/reference/cli/cli-options.qdocinc
index d4c3280a2..f609b1964 100644
--- a/doc/reference/cli/cli-options.qdocinc
+++ b/doc/reference/cli/cli-options.qdocinc
@@ -201,6 +201,7 @@
\list
\li \c clangdb
\li \c visualstudio2015
+ \li \c iarew8
\endlist
The available generators are listed if you run the \c {qbs generate} command
diff --git a/doc/reference/commands.qdoc b/doc/reference/commands.qdoc
index eb93e8f7a..d34c20cb7 100644
--- a/doc/reference/commands.qdoc
+++ b/doc/reference/commands.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -116,6 +117,14 @@
\li A flag that controls whether the \c description is printed. Set it to \c true for commands that
users need not know about. \note If this property is \c false, then \c description must
not be empty.
+ \row
+ \li \c timeout
+ \li int
+ \li -1
+ \li Time limit for the command execution in seconds. If the command does not finish within
+ the timeout, it is cancelled. In case of a \c Command, the process is requested to
+ terminate. If it does not terminate within three seconds, it is killed. A value below
+ or equal to 0 means no timeout.
\endtable
\section2 Command Properties
diff --git a/examples/baremetal/at90can128olimex/redblink/redblink.qbs b/examples/baremetal/at90can128olimex/redblink/redblink.qbs
index bbc0d7261..84323e3c1 100644
--- a/examples/baremetal/at90can128olimex/redblink/redblink.qbs
+++ b/examples/baremetal/at90can128olimex/redblink/redblink.qbs
@@ -57,7 +57,7 @@ CppApplication {
return qbs.toolchain.contains("gcc")
|| qbs.toolchain.contains("iar")
}
- name: "redblink"
+ name: "at90can128olimex-redblink"
cpp.cLanguageVersion: "c99"
cpp.positionIndependentCode: false
diff --git a/examples/baremetal/baremetal.qbs b/examples/baremetal/baremetal.qbs
index 08d41793f..3481dbd75 100644
--- a/examples/baremetal/baremetal.qbs
+++ b/examples/baremetal/baremetal.qbs
@@ -55,6 +55,7 @@ Project {
references: [
"stm32f4discovery/stm32f4discovery.qbs",
"at90can128olimex/at90can128olimex.qbs",
- "cc2540usbdongle/cc2540usbdongle.qbs"
+ "cc2540usbdongle/cc2540usbdongle.qbs",
+ "stm8s103f3/stm8s103f3.qbs",
]
}
diff --git a/examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs b/examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs
index eb0be6b34..e8aa3d1fd 100644
--- a/examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs
+++ b/examples/baremetal/cc2540usbdongle/greenblink/greenblink.qbs
@@ -58,7 +58,7 @@ CppApplication {
|| qbs.toolchain.contains("keil")
|| qbs.toolchain.contains("sdcc")
}
- name: "greenblink"
+ name: "cc2540usbdongle-greenblink"
cpp.positionIndependentCode: false
//
@@ -111,8 +111,7 @@ CppApplication {
Properties {
condition: qbs.toolchain.contains("sdcc")
- cpp.commonCompilerFlags: ["-mmcs51"]
- }
+ }
//
// Common code.
diff --git a/examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs b/examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs
index 9b131fa71..5ccf8b3b0 100644
--- a/examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs
+++ b/examples/baremetal/stm32f4discovery/blueblink/blueblink.qbs
@@ -58,7 +58,7 @@ CppApplication {
|| qbs.toolchain.contains("iar")
|| qbs.toolchain.contains("keil")
}
- name: "blueblink"
+ name: "stm32f4discovery-blueblink"
cpp.cLanguageVersion: "c99"
cpp.positionIndependentCode: false
diff --git a/examples/baremetal/stm8s103f3/redblink/README.md b/examples/baremetal/stm8s103f3/redblink/README.md
new file mode 100644
index 000000000..2c76e918e
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/README.md
@@ -0,0 +1,8 @@
+This example demonstrates how to build a bare-metal application using
+different STM8 toolchains. It is designed for the STM8 target board
+(based on STMicroelectronics stm8s103f3 MCU) and simply flashes the
+red LED on the board.
+
+The following toolchains are supported:
+
+ * IAR Embedded Workbench
diff --git a/examples/baremetal/stm8s103f3/redblink/gpio.c b/examples/baremetal/stm8s103f3/redblink/gpio.c
new file mode 100644
index 000000000..cc68c732c
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/gpio.c
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gpio.h"
+#include "system.h"
+
+// A LED is connected to the pin #5 of Port B.
+#define GPIO_RED_LED_PIN_POS (0x20u)
+
+void gpio_init_red_led(void)
+{
+ PB_ODR = 0x00; // Turn off all pins.
+ PB_DDR = GPIO_RED_LED_PIN_POS; // Configure Pin as output.
+ PB_CR1 = GPIO_RED_LED_PIN_POS; // Set Pin to Push-Pull.
+ PB_CR2 = GPIO_RED_LED_PIN_POS; // Set Pin to Push-Pull.
+}
+
+void gpio_toggle_red_led(void)
+{
+ PB_ODR ^= GPIO_RED_LED_PIN_POS;
+}
diff --git a/examples/baremetal/stm8s103f3/redblink/gpio.h b/examples/baremetal/stm8s103f3/redblink/gpio.h
new file mode 100644
index 000000000..246eab860
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/gpio.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GPIO_H
+#define GPIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gpio_init_red_led(void);
+void gpio_toggle_red_led(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GPIO_H
diff --git a/examples/baremetal/stm8s103f3/redblink/main.c b/examples/baremetal/stm8s103f3/redblink/main.c
new file mode 100644
index 000000000..63c1c0aec
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/main.c
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gpio.h"
+#include "system.h"
+
+static void some_delay(unsigned long counts)
+{
+ unsigned long index = 0u;
+ for (index = 0u; index < counts; ++index)
+ system_nop();
+}
+
+int main(void)
+{
+ gpio_init_red_led();
+
+ while (1) {
+ gpio_toggle_red_led();
+ some_delay(20000u);
+ }
+}
diff --git a/examples/baremetal/stm8s103f3/redblink/redblink.qbs b/examples/baremetal/stm8s103f3/redblink/redblink.qbs
new file mode 100644
index 000000000..197bae8ae
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/redblink.qbs
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs
+
+CppApplication {
+ condition: {
+ if (!qbs.architecture.contains("stm8"))
+ return false;
+ return qbs.toolchain.contains("iar")
+ || qbs.toolchain.contains("sdcc")
+ }
+ name: "stm8s103f3-redblink"
+ cpp.positionIndependentCode: false
+
+ //
+ // IAR-specific properties and sources.
+ //
+
+ Properties {
+ condition: qbs.toolchain.contains("iar")
+ cpp.commonCompilerFlags: ["-e"]
+ cpp.driverLinkerFlags: [
+ "--config_def", "_CSTACK_SIZE=0x100",
+ "--config_def", "_HEAP_SIZE=0x100",
+ ]
+ }
+
+ Group {
+ condition: qbs.toolchain.contains("iar")
+ name: "IAR"
+ prefix: "iar/"
+ Group {
+ name: "Linker Script"
+ prefix: cpp.toolchainInstallPath + "/../config/"
+ fileTags: ["linkerscript"]
+ files: ["lnkstm8s103f3.icf"]
+ }
+ }
+
+ //
+ // SDCC-specific properties and sources.
+ //
+
+ Properties {
+ condition: qbs.toolchain.contains("sdcc")
+ }
+
+ //
+ // Common code.
+ //
+
+ Group {
+ name: "Gpio"
+ files: ["gpio.c", "gpio.h"]
+ }
+
+ Group {
+ name: "System"
+ files: ["system.h"]
+ }
+
+ files: ["main.c"]
+}
diff --git a/examples/baremetal/stm8s103f3/redblink/system.h b/examples/baremetal/stm8s103f3/redblink/system.h
new file mode 100644
index 000000000..463123ce2
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/redblink/system.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Define required registers of Port B (where the LED is connected):
+// * PB_ODR - Output Data Register.
+// * PB_DDR - Data Direction Register.
+// * PB_CR1 - Control Register #1.
+// * PB_CR2 - Control Register #2.
+
+#if defined(__ICCSTM8__)
+# define system_nop() __asm("nop")
+__near __no_init volatile unsigned char PB_ODR @ 0x5005;
+__near __no_init volatile unsigned char PB_DDR @ 0x5007;
+__near __no_init volatile unsigned char PB_CR1 @ 0x5008;
+__near __no_init volatile unsigned char PB_CR2 @ 0x5009;
+#elif defined (__SDCC_stm8)
+# define system_nop() __asm nop __endasm
+#define PB_ODR *(volatile unsigned char *)0x5005
+#define PB_DDR *(volatile unsigned char *)0x5007
+#define PB_CR1 *(volatile unsigned char *)0x5008
+#define PB_CR2 *(volatile unsigned char *)0x5009
+#else
+#error "Unsupported toolchain"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SYSTEM_H
diff --git a/examples/baremetal/stm8s103f3/stm8s103f3.qbs b/examples/baremetal/stm8s103f3/stm8s103f3.qbs
new file mode 100644
index 000000000..922c4c1f0
--- /dev/null
+++ b/examples/baremetal/stm8s103f3/stm8s103f3.qbs
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs
+
+Project {
+ name: "Examples for stm8s103f3 board"
+ references: [
+ "redblink/redblink.qbs"
+ ]
+}
diff --git a/examples/collidingmice/collidingmice.qbs b/examples/collidingmice/collidingmice.qbs
index 312f6b0ab..52231882e 100644
--- a/examples/collidingmice/collidingmice.qbs
+++ b/examples/collidingmice/collidingmice.qbs
@@ -50,7 +50,7 @@
import qbs 1.0
-Application {
+CppApplication {
name : "CollidingMice"
Depends { name: "Qt.widgets" }
property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle
@@ -64,7 +64,7 @@ Application {
Group {
fileTagsFilter: isBundle ? ["bundle.content"] : ["application"]
qbs.install: true
- qbs.installPrefix: isBundle ? "Applications" : "bin"
+ qbs.installDir: isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin")
qbs.installSourceBase: product.buildDirectory
}
}
diff --git a/scripts/build-qbs-with-qbs.sh b/scripts/build-qbs-with-qbs.sh
index deb3a138b..503f3fbff 100755
--- a/scripts/build-qbs-with-qbs.sh
+++ b/scripts/build-qbs-with-qbs.sh
@@ -40,12 +40,6 @@
set -e
#
-# It might be desired to keep settings for Qbs testing
-# in a separate folder.
-#
-export QBS_AUTOTEST_SETTINGS_DIR="${QBS_AUTOTEST_SETTINGS_DIR:-/tmp/qbs-settings}"
-
-#
# Qbs is built with the address sanitizer enabled.
# Suppress findings in some parts of Qbs / dependencies.
#
@@ -60,6 +54,7 @@ BUILD_OPTIONS="\
modules.qbsbuildconfig.enableProjectFileUpdates:true \
modules.qbsbuildconfig.enableUnitTests:true \
project.withExamples:true \
+ ${BUILD_OPTIONS}
"
#
@@ -67,7 +62,11 @@ BUILD_OPTIONS="\
#
qbs resolve ${BUILD_OPTIONS}
qbs build ${BUILD_OPTIONS}
-qbs build -p "qbs documentation" ${BUILD_OPTIONS}
+
+WITH_DOCS=${WITH_DOCS:-1}
+if [ "$WITH_DOCS" -ne 0 ]; then
+ qbs build -p "qbs documentation" ${BUILD_OPTIONS}
+fi
#
# Set up profiles for the freshly built Qbs if not
@@ -76,6 +75,7 @@ qbs build -p "qbs documentation" ${BUILD_OPTIONS}
if [ -z "${QBS_AUTOTEST_PROFILE}" ]; then
export QBS_AUTOTEST_PROFILE=autotestprofile
+ export QBS_AUTOTEST_SETTINGS_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'qbs-settings'`
RUN_OPTIONS="\
--settings-dir ${QBS_AUTOTEST_SETTINGS_DIR} \
@@ -89,9 +89,16 @@ if [ -z "${QBS_AUTOTEST_PROFILE}" ]; then
${RUN_OPTIONS} \
"${QMAKE_PATH:-$(which qmake)}" ${QBS_AUTOTEST_PROFILE}
- qbs run -p qbs_app ${BUILD_OPTIONS} -- config \
- ${RUN_OPTIONS} \
- ${QBS_AUTOTEST_PROFILE}.baseProfile gcc
+ # Make sure that the Qt profile uses the same toolchain profile
+ # that was used for building in case a custom QBS_BUILD_PROFILE
+ # was set. Otherwise setup-qt automatically uses the default
+ # toolchain profile.
+ if [ ! -z "${QBS_BUILD_PROFILE}" ]; then
+ QBS_BUILD_BASE_PROFILE=$(qbs config ${QBS_BUILD_PROFILE}.baseProfile | cut -d: -f2)
+ qbs run -p qbs_app ${BUILD_OPTIONS} -- config \
+ ${RUN_OPTIONS} \
+ ${QBS_AUTOTEST_PROFILE}.baseProfile ${QBS_BUILD_BASE_PROFILE}
+ fi
# QBS_AUTOTEST_PROFILE has been added to the environment
# which requires a resolve step
diff --git a/share/qbs/imports/qbs/Probes/IarProbe.qbs b/share/qbs/imports/qbs/Probes/IarProbe.qbs
index 6e7fb7d64..c57878058 100644
--- a/share/qbs/imports/qbs/Probes/IarProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/IarProbe.qbs
@@ -91,6 +91,10 @@ PathProbe {
versionMajor = parseInt(version / 100);
versionMinor = parseInt(version % 100);
versionPatch = 0;
+ } else if (architecture === "stm8") {
+ versionMajor = parseInt(version / 100);
+ versionMinor = parseInt(version % 100);
+ versionPatch = 0;
}
found = version && architecture && endianness;
diff --git a/share/qbs/imports/qbs/base/AutotestRunner.qbs b/share/qbs/imports/qbs/base/AutotestRunner.qbs
index ab9ba15f7..b9adee88d 100644
--- a/share/qbs/imports/qbs/base/AutotestRunner.qbs
+++ b/share/qbs/imports/qbs/base/AutotestRunner.qbs
@@ -42,6 +42,7 @@ Product {
property stringList wrapper: []
property string workingDir
property stringList auxiliaryInputs
+ property int timeout: -1
Depends {
productTypes: "autotest"
@@ -74,6 +75,7 @@ Product {
: FileInfo.path(commandFilePath);
var arguments = product.arguments;
var allowFailure = false;
+ var timeout = product.timeout;
if (input.autotest) {
// FIXME: We'd like to let the user override with an empty list, but
// qbscore turns undefined lists into empty ones at the moment.
@@ -83,6 +85,9 @@ Product {
if (input.autotest.workingDir)
workingDir = input.autotest.workingDir;
allowFailure = input.autotest.allowFailure;
+
+ if (input.autotest.timeout !== undefined)
+ timeout = input.autotest.timeout;
}
var fullCommandLine = product.wrapper
.concat([commandFilePath])
@@ -91,6 +96,7 @@ Product {
cmd.description = "Running test " + input.fileName;
cmd.environment = product.environment;
cmd.workingDirectory = workingDir;
+ cmd.timeout = timeout;
if (allowFailure)
cmd.maxExitCode = 32767;
return cmd;
diff --git a/share/qbs/modules/autotest/autotest.qbs b/share/qbs/modules/autotest/autotest.qbs
index ba280169e..c8a1c5180 100644
--- a/share/qbs/modules/autotest/autotest.qbs
+++ b/share/qbs/modules/autotest/autotest.qbs
@@ -2,4 +2,5 @@ Module {
property stringList arguments
property bool allowFailure: false
property string workingDir
+ property int timeout
}
diff --git a/share/qbs/modules/cpp/iar.js b/share/qbs/modules/cpp/iar.js
index 33093c0a3..ddaa00e2d 100644
--- a/share/qbs/modules/cpp/iar.js
+++ b/share/qbs/modules/cpp/iar.js
@@ -47,6 +47,8 @@ function guessArchitecture(macros)
return "mcs51";
else if (macros["__ICCAVR__"] === "1")
return "avr";
+ else if (macros["__ICCSTM8__"] === "1")
+ return "stm8";
}
function guessEndianness(macros)
@@ -248,6 +250,8 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
args.push("--ec++");
} else if (input.qbs.architecture === "avr") {
args.push("--ec++");
+ } else if (input.qbs.architecture === "stm8") {
+ args.push("--ec++");
}
}
@@ -295,10 +299,20 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) {
args.push("-r");
var warnings = input.cpp.warningLevel;
- if (warnings === "none")
- args.push("-w-");
- else
- args.push("-w+");
+ if (warnings === "none") {
+ if (input.qbs.architecture === "stm8")
+ args.push("--no_warnings");
+ else
+ args.push("-w-");
+ } else {
+ if (input.qbs.architecture !== "stm8")
+ args.push("-w+");
+ }
+
+ if (input.cpp.treatWarningsAsErrors) {
+ if (input.qbs.architecture === "stm8")
+ args.push("--warnings_are_errors");
+ }
var allIncludePaths = [];
var systemIncludePaths = input.cpp.systemIncludePaths;
@@ -311,7 +325,10 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) {
args.push("-o", output.filePath);
- args.push("-S"); // Silent operation.
+ if (input.qbs.architecture === "stm8")
+ args.push("--silent"); // Silent operation.
+ else
+ args.push("-S"); // Silent operation.
args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag),
ModUtils.moduleProperty(input, "flags", tag),
@@ -335,6 +352,8 @@ function linkerFlags(project, product, input, outputs) {
args.push("-l", outputs.map_file[0].filePath);
else if (product.qbs.architecture === "avr")
args.push("-l", outputs.map_file[0].filePath);
+ else if (product.qbs.architecture === "stm8")
+ args.push("--map", outputs.map_file[0].filePath);
}
var allLibraryPaths = [];
@@ -366,6 +385,8 @@ function linkerFlags(project, product, input, outputs) {
args.push("-f", linkerScripts[i]);
else if (product.qbs.architecture === "avr")
args.push("-f", linkerScripts[i]);
+ else if (product.qbs.architecture === "stm8")
+ args.push("--config", linkerScripts[i]);
}
if (product.cpp.entryPoint) {
@@ -375,6 +396,8 @@ function linkerFlags(project, product, input, outputs) {
args.push("-s", product.cpp.entryPoint);
else if (product.qbs.architecture === "avr")
args.push("-s", product.cpp.entryPoint);
+ else if (product.qbs.architecture === "stm8")
+ args.push("--entry", product.cpp.entryPoint);
}
if (product.qbs.architecture === "arm")
@@ -383,6 +406,8 @@ function linkerFlags(project, product, input, outputs) {
args.push("-S"); // Silent operation.
else if (product.qbs.architecture === "avr")
args.push("-S"); // Silent operation.
+ else if (product.qbs.architecture === "stm8")
+ args.push("--silent"); // Silent operation.
args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags"));
return args;
diff --git a/share/qbs/modules/cpp/iar.qbs b/share/qbs/modules/cpp/iar.qbs
index 6d15781a5..8b8773f7c 100644
--- a/share/qbs/modules/cpp/iar.qbs
+++ b/share/qbs/modules/cpp/iar.qbs
@@ -86,6 +86,8 @@ CppModule {
return "icc8051" + compilerExtension;
case "avr":
return "iccavr" + compilerExtension;
+ case "stm8":
+ return "iccstm8" + compilerExtension;
}
}
compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
@@ -98,6 +100,8 @@ CppModule {
return "a8051" + compilerExtension;
case "avr":
return "aavr" + compilerExtension;
+ case "stm8":
+ return "iasmstm8" + compilerExtension;
}
}
assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
@@ -110,6 +114,8 @@ CppModule {
return "xlink" + compilerExtension;
case "avr":
return "xlink" + compilerExtension;
+ case "stm8":
+ return "ilinkstm8" + compilerExtension;
}
}
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
@@ -122,6 +128,8 @@ CppModule {
return "xlib" + compilerExtension;
case "avr":
return "xlib" + compilerExtension;
+ case "stm8":
+ return "iarchive" + compilerExtension;
}
}
property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
@@ -136,6 +144,8 @@ CppModule {
return ".r51";
case "avr":
return ".r90";
+ case "stm8":
+ return ".a";
}
}
@@ -147,6 +157,8 @@ CppModule {
return qbs.debugInformation ? ".d51" : ".a51";
case "avr":
return qbs.debugInformation ? ".d90" : ".a90";
+ case "stm8":
+ return ".out";
}
}
@@ -158,6 +170,8 @@ CppModule {
return ".r51";
case "avr":
return ".r90";
+ case "stm8":
+ return ".o";
}
}
@@ -169,6 +183,8 @@ CppModule {
return "ubrof";
case "avr":
return "ubrof";
+ case "stm8":
+ return "elf";
}
}
@@ -189,7 +205,7 @@ CppModule {
}
FileTagger {
- condition: qbs.architecture === "arm";
+ condition: qbs.architecture === "arm" || qbs.architecture === "stm8";
patterns: "*.s"
fileTags: ["asm"]
}
diff --git a/share/qbs/modules/cpp/sdcc.js b/share/qbs/modules/cpp/sdcc.js
index 2f148d2c2..4ce380d16 100644
--- a/share/qbs/modules/cpp/sdcc.js
+++ b/share/qbs/modules/cpp/sdcc.js
@@ -42,12 +42,16 @@ var WindowsUtils = require("qbs.WindowsUtils");
function targetArchitectureFlag(architecture) {
if (architecture === "mcs51")
return "-mmcs51";
+ if (architecture === "stm8")
+ return "-mstm8";
}
function guessArchitecture(macros)
{
if (macros["__SDCC_mcs51"] === "1")
return "mcs51";
+ if (macros["__SDCC_stm8"] === "1")
+ return "stm8";
}
function guessEndianness(macros)
@@ -188,6 +192,10 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
args.push("-c");
args.push("-o", output.filePath);
+ var targetFlag = targetArchitectureFlag(input.cpp.architecture);
+ if (targetFlag)
+ args.push(targetFlag);
+
switch (input.cpp.optimization) {
case "small":
args.push("--opt-code-size");
@@ -273,6 +281,10 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) {
function linkerFlags(project, product, input, outputs) {
var args = [];
+ var targetFlag = targetArchitectureFlag(product.cpp.architecture);
+ if (targetFlag)
+ args.push(targetFlag);
+
var allLibraryPaths = [];
var libraryPaths = product.cpp.libraryPaths;
if (libraryPaths)
diff --git a/share/qbs/modules/cpp/sdcc.qbs b/share/qbs/modules/cpp/sdcc.qbs
index a0d795b40..0be9d22c4 100644
--- a/share/qbs/modules/cpp/sdcc.qbs
+++ b/share/qbs/modules/cpp/sdcc.qbs
@@ -87,6 +87,8 @@ CppModule {
switch (qbs.architecture) {
case "mcs51":
return "sdas8051" + compilerExtension;
+ case "stm8":
+ return "sdasstm8" + compilerExtension;
}
}
assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
@@ -95,6 +97,8 @@ CppModule {
switch (qbs.architecture) {
case "mcs51":
return "sdld" + compilerExtension;
+ case "stm8":
+ return "sdldstm8" + compilerExtension;
}
}
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
diff --git a/src/app/qbs-setup-toolchains/clangclprobe.cpp b/src/app/qbs-setup-toolchains/clangclprobe.cpp
index 5c2a87731..816d28546 100644
--- a/src/app/qbs-setup-toolchains/clangclprobe.cpp
+++ b/src/app/qbs-setup-toolchains/clangclprobe.cpp
@@ -60,9 +60,9 @@ using qbs::Internal::Tr;
namespace {
-QString getToolchainInstallPath(const QString &compilerFilePath)
+QString getToolchainInstallPath(const QFileInfo &compiler)
{
- return QFileInfo(compilerFilePath).path(); // 1 level up
+ return compiler.path(); // 1 level up
}
Profile createProfileHelper(
@@ -159,19 +159,19 @@ QString findClangCl()
} // namespace
-void createClangClProfile(
- const QString &profileName, const QString &compilerFilePath, Settings *settings)
+void createClangClProfile(const QFileInfo &compiler, Settings *settings,
+ const QString &profileName)
{
const auto compilerName = QStringLiteral("clang-cl");
const auto vcvarsallPath = findCompatibleVcsarsallBat();
if (vcvarsallPath.isEmpty()) {
qbsWarning()
<< Tr::tr("%1 requires installed Visual Studio 2017 or newer, but none was found.")
- .arg(compilerName);
+ .arg(compilerName);
return;
}
- const auto toolchainInstallPath = getToolchainInstallPath(compilerFilePath);
+ const auto toolchainInstallPath = getToolchainInstallPath(compiler);
const auto hostArch = QString::fromStdString(HostOsInfo::hostOSArchitecture());
createProfileHelper(settings, profileName, toolchainInstallPath, vcvarsallPath, hostArch);
}
@@ -184,12 +184,12 @@ void clangClProbe(Settings *settings, QList<Profile> &profiles)
{
const auto compilerName = QStringLiteral("clang-cl");
qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName);
- const auto compilerFilePath = findClangCl();
+ const QString compilerFilePath = findClangCl();
if (compilerFilePath.isEmpty()) {
qbsInfo() << Tr::tr("%1 was not found.").arg(compilerName);
return;
}
-
+ const QFileInfo compiler(compilerFilePath);
const auto vcvarsallPath = findCompatibleVcsarsallBat();
if (vcvarsallPath.isEmpty()) {
qbsWarning()
@@ -202,7 +202,7 @@ void clangClProbe(Settings *settings, QList<Profile> &profiles)
QStringLiteral("x86_64"),
QStringLiteral("x86")
};
- const auto toolchainInstallPath = getToolchainInstallPath(compilerFilePath);
+ const auto toolchainInstallPath = getToolchainInstallPath(compiler);
for (const auto &arch: architectures) {
const auto profileName = QStringLiteral("clang-cl-%1").arg(arch);
auto profile = createProfileHelper(
diff --git a/src/app/qbs-setup-toolchains/clangclprobe.h b/src/app/qbs-setup-toolchains/clangclprobe.h
index 1e7724fbf..1afbbb1b8 100644
--- a/src/app/qbs-setup-toolchains/clangclprobe.h
+++ b/src/app/qbs-setup-toolchains/clangclprobe.h
@@ -37,19 +37,23 @@
**
****************************************************************************/
-#ifndef CLANGCLPROBE_H
-#define CLANGCLPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H
+#define QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H
#include <QtCore/qlist.h>
+QT_BEGIN_NAMESPACE
+class QFileInfo;
+QT_END_NAMESPACE
+
namespace qbs {
class Profile;
class Settings;
}
-void createClangClProfile(
- const QString &profileName, const QString &compilerFilePath, qbs::Settings *settings);
+void createClangClProfile(const QFileInfo &compiler, qbs::Settings *settings,
+ const QString &profileName);
void clangClProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // CLANGCLPROBE_H
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/commandlineparser.h b/src/app/qbs-setup-toolchains/commandlineparser.h
index 9d5b0c246..0616f068e 100644
--- a/src/app/qbs-setup-toolchains/commandlineparser.h
+++ b/src/app/qbs-setup-toolchains/commandlineparser.h
@@ -36,6 +36,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H
#define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H
@@ -75,4 +76,4 @@ private:
QString m_command;
};
-#endif // Include guard
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/gccprobe.cpp b/src/app/qbs-setup-toolchains/gccprobe.cpp
new file mode 100644
index 000000000..e979acf59
--- /dev/null
+++ b/src/app/qbs-setup-toolchains/gccprobe.cpp
@@ -0,0 +1,477 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "probe.h"
+#include "gccprobe.h"
+
+#include "../shared/logging/consolelogger.h"
+
+#include <logging/translator.h>
+
+#include <tools/hostosinfo.h>
+#include <tools/profile.h>
+#include <tools/toolchains.h>
+
+#include <QtCore/qdir.h>
+#include <QtCore/qprocess.h>
+
+using namespace qbs;
+using Internal::HostOsInfo;
+using Internal::Tr;
+
+static QString qsystem(const QString &exe, const QStringList &args = QStringList())
+{
+ QProcess p;
+ p.setProcessChannelMode(QProcess::MergedChannels);
+ p.start(exe, args);
+ if (!p.waitForStarted()) {
+ throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2")
+ .arg(exe, p.errorString()));
+ }
+ if (!p.waitForFinished(-1) || p.exitCode() != 0)
+ throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2")
+ .arg(exe, p.errorString()));
+ return QString::fromLocal8Bit(p.readAll());
+}
+
+static QStringList validMinGWMachines()
+{
+ // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs
+ return {QStringLiteral("mingw32"),
+ QStringLiteral("mingw64"),
+ QStringLiteral("i686-w64-mingw32"),
+ QStringLiteral("x86_64-w64-mingw32"),
+ QStringLiteral("i686-w64-mingw32.shared"),
+ QStringLiteral("x86_64-w64-mingw32.shared"),
+ QStringLiteral("i686-w64-mingw32.static"),
+ QStringLiteral("x86_64-w64-mingw32.static"),
+ QStringLiteral("i586-mingw32msvc"),
+ QStringLiteral("amd64-mingw32msvc")};
+}
+
+static QString gccMachineName(const QFileInfo &compiler)
+{
+ return qsystem(compiler.absoluteFilePath(), {QStringLiteral("-dumpmachine")})
+ .trimmed();
+}
+
+static QStringList standardCompilerFileNames()
+{
+ return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")),
+ HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")),
+ HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")),
+ HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))};
+}
+
+class ToolchainDetails
+{
+public:
+ explicit ToolchainDetails(const QFileInfo &compiler)
+ {
+ auto baseName = compiler.completeBaseName();
+ if (baseName.contains(QRegExp(QLatin1String("\\d$")))) {
+ const auto dashIndex = baseName.lastIndexOf(QLatin1Char('-'));
+ version = baseName.mid(dashIndex + 1);
+ baseName = baseName.left(dashIndex);
+ }
+
+ const auto dashIndex = baseName.lastIndexOf(QLatin1Char('-'));
+ suffix = baseName.mid(dashIndex + 1);
+ prefix = baseName.left(dashIndex + 1);
+ }
+
+ QString prefix;
+ QString suffix;
+ QString version;
+};
+
+static void setCommonProperties(Profile &profile, const QFileInfo &compiler,
+ const QStringList &toolchainTypes, const ToolchainDetails &details)
+{
+ if (toolchainTypes.contains(QStringLiteral("mingw")))
+ profile.setValue(QStringLiteral("qbs.targetPlatform"),
+ QStringLiteral("windows"));
+
+ if (!details.prefix.isEmpty())
+ profile.setValue(QStringLiteral("cpp.toolchainPrefix"), details.prefix);
+
+ profile.setValue(QStringLiteral("cpp.toolchainInstallPath"),
+ compiler.absolutePath());
+ profile.setValue(QStringLiteral("qbs.toolchain"), toolchainTypes);
+
+ if (!standardCompilerFileNames().contains(
+ HostOsInfo::appendExecutableSuffix(details.suffix))) {
+ qWarning("%s", qPrintable(
+ QStringLiteral("'%1' is not a standard compiler file name; "
+ "you must set the cpp.cCompilerName and "
+ "cpp.cxxCompilerName properties of this profile "
+ "manually").arg(compiler.fileName())));
+ }
+}
+
+class ToolPathSetup
+{
+public:
+ explicit ToolPathSetup(Profile *profile, QString path, ToolchainDetails details)
+ : m_profile(profile),
+ m_compilerDirPath(std::move(path)),
+ m_details(std::move(details))
+ {
+ }
+
+ void apply(const QString &toolName, const QString &propertyName) const
+ {
+ // Check for full tool name at first (includes suffix and version).
+ QString filePath = toolFilePath(toolName, UseFullToolName);
+ if (filePath.isEmpty()) {
+ // Check for base tool name at second (without of suffix and version).
+ filePath = toolFilePath(toolName, UseBaseToolName);
+ if (filePath.isEmpty()) {
+ // Check for short tool name at third (only a tool name).
+ filePath = toolFilePath(toolName, UseOnlyShortToolName);
+ }
+ }
+
+ if (filePath.isEmpty()) {
+ qWarning("%s", qPrintable(
+ QStringLiteral("'%1' not found in '%2'. "
+ "Qbs will try to find it in PATH at build time.")
+ .arg(toolName, m_compilerDirPath)));
+ } else {
+ m_profile->setValue(propertyName, filePath);
+ }
+ }
+
+private:
+ enum ToolNameParts : quint8 {
+ UseOnlyShortToolName = 0x0,
+ UseToolPrefix = 0x01,
+ UseToolSuffix = 0x02,
+ UseToolVersion = 0x04,
+ UseFullToolName = UseToolPrefix | UseToolSuffix | UseToolVersion,
+ UseBaseToolName = UseToolPrefix,
+ };
+
+ QString toolFilePath(const QString &toolName, int parts) const
+ {
+ QString fileName;
+ if ((parts & UseToolPrefix) && !m_details.prefix.isEmpty())
+ fileName += m_details.prefix;
+ if ((parts & UseToolSuffix) && !m_details.suffix.isEmpty())
+ fileName += m_details.suffix + QLatin1Char('-');
+ fileName += toolName;
+ if ((parts & UseToolVersion) && !m_details.version.isEmpty())
+ fileName += QLatin1Char('-') + m_details.version;
+
+ fileName = HostOsInfo::appendExecutableSuffix(fileName);
+ QString filePath = QDir(m_compilerDirPath).absoluteFilePath(fileName);
+ if (QFile::exists(filePath))
+ return filePath;
+ return {};
+ }
+
+ Profile * const m_profile;
+ QString m_compilerDirPath;
+ ToolchainDetails m_details;
+};
+
+static bool doesProfileTargetOS(const Profile &profile, const QString &os)
+{
+ const auto target = profile.value(QStringLiteral("qbs.targetPlatform"));
+ if (target.isValid()) {
+ return Internal::contains(HostOsInfo::canonicalOSIdentifiers(
+ target.toString().toStdString()),
+ os.toStdString());
+ }
+ return Internal::contains(HostOsInfo::hostOSIdentifiers(), os.toStdString());
+}
+
+static QString buildProfileName(const QFileInfo &cfi)
+{
+ // We need to replace a dot-separated compiler version string
+ // with a underscore-separated string, because the profile
+ // name does not allow a dots.
+ auto result = cfi.completeBaseName();
+ result.replace(QLatin1Char('.'), QLatin1Char('_'));
+ return result;
+}
+
+static QStringList buildCompilerNameFilters(const QString &compilerName)
+{
+ QStringList filters = {
+ // "clang", "gcc"
+ compilerName,
+ // "clang-8", "gcc-5"
+ compilerName + QLatin1String("-[1-9]*"),
+ // "avr-gcc"
+ QLatin1String("*-") + compilerName,
+ // "avr-gcc-5.4.0"
+ QLatin1String("*-") + compilerName + QLatin1String("-[1-9]*"),
+ // "arm-none-eabi-gcc"
+ QLatin1String("*-*-*-") + compilerName,
+ // "arm-none-eabi-gcc-9.1.0"
+ QLatin1String("*-*-*-") + compilerName + QLatin1String("-[1-9]*"),
+ // "x86_64-pc-linux-gnu-gcc"
+ QLatin1String("*-*-*-*-") + compilerName,
+ // "x86_64-pc-linux-gnu-gcc-7.4.1"
+ QLatin1String("*-*-*-*-") + compilerName + QLatin1String("-[1-9]*")
+ };
+
+ std::transform(filters.begin(), filters.end(), filters.begin(),
+ [](const auto &filter) {
+ return HostOsInfo::appendExecutableSuffix(filter);
+ });
+
+ return filters;
+}
+
+static QStringList gnuRegistrySearchPaths()
+{
+ if (!HostOsInfo::isWindowsHost())
+ return {};
+
+ // Registry token for the "GNU Tools for ARM Embedded Processors".
+ static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \
+ "Windows\\CurrentVersion\\Uninstall\\";
+
+ QStringList searchPaths;
+
+ QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat);
+ const auto productGroups = registry.childGroups();
+ for (const QString &productKey : productGroups) {
+ if (!productKey.startsWith(
+ QLatin1String("GNU Tools for ARM Embedded Processors"))) {
+ continue;
+ }
+ registry.beginGroup(productKey);
+ QString uninstallFilePath = registry.value(
+ QLatin1String("UninstallString")).toString();
+ if (uninstallFilePath.startsWith(QLatin1Char('"')))
+ uninstallFilePath.remove(0, 1);
+ if (uninstallFilePath.endsWith(QLatin1Char('"')))
+ uninstallFilePath.remove(uninstallFilePath.size() - 1, 1);
+ registry.endGroup();
+
+ const QString toolkitRootPath = QFileInfo(uninstallFilePath).path();
+ const QString toolchainPath = toolkitRootPath + QLatin1String("/bin");
+ searchPaths.push_back(toolchainPath);
+ }
+
+ return searchPaths;
+}
+
+static QStringList atmelRegistrySearchPaths()
+{
+ if (!HostOsInfo::isWindowsHost())
+ return {};
+
+ // Registry token for the "Atmel" toolchains, e.g. provided by installed
+ // "Atmel Studio" IDE.
+ static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Atmel\\";
+
+ QStringList searchPaths;
+ QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat);
+
+ // This code enumerate the installed toolchains provided
+ // by the Atmel Studio v6.x.
+ const auto toolchainGroups = registry.childGroups();
+ for (const QString &toolchainKey : toolchainGroups) {
+ if (!toolchainKey.endsWith(QLatin1String("GCC")))
+ continue;
+ registry.beginGroup(toolchainKey);
+ const auto entries = registry.childGroups();
+ for (const auto &entryKey : entries) {
+ registry.beginGroup(entryKey);
+ const QString installDir = registry.value(
+ QStringLiteral("Native/InstallDir")).toString();
+ const QString version = registry.value(
+ QStringLiteral("Native/Version")).toString();
+ registry.endGroup();
+
+ QString toolchainPath = installDir
+ + QLatin1String("/Atmel Toolchain/")
+ + toolchainKey + QLatin1String("/Native/")
+ + version;
+ if (toolchainKey.startsWith(QLatin1String("ARM")))
+ toolchainPath += QLatin1String("/arm-gnu-toolchain");
+ else if (toolchainKey.startsWith(QLatin1String("AVR32")))
+ toolchainPath += QLatin1String("/avr32-gnu-toolchain");
+ else if (toolchainKey.startsWith(QLatin1String("AVR8)")))
+ toolchainPath += QLatin1String("/avr8-gnu-toolchain");
+ else
+ break;
+
+ toolchainPath += QLatin1String("/bin");
+
+ if (QFileInfo::exists(toolchainPath)) {
+ searchPaths.push_back(toolchainPath);
+ break;
+ }
+ }
+ registry.endGroup();
+ }
+
+ // This code enumerate the installed toolchains provided
+ // by the Atmel Studio v7.
+ registry.beginGroup(QStringLiteral("AtmelStudio"));
+ const auto productVersions = registry.childGroups();
+ for (const auto &productVersionKey : productVersions) {
+ registry.beginGroup(productVersionKey);
+ const QString installDir = registry.value(
+ QStringLiteral("InstallDir")).toString();
+ registry.endGroup();
+
+ const QStringList knownToolchainSubdirs = {
+ QStringLiteral("/toolchain/arm/arm-gnu-toolchain/bin/"),
+ QStringLiteral("/toolchain/avr8/avr8-gnu-toolchain/bin/"),
+ QStringLiteral("/toolchain/avr32/avr32-gnu-toolchain/bin/"),
+ };
+
+ for (const auto &subdir : knownToolchainSubdirs) {
+ const QString toolchainPath = installDir + subdir;
+ if (!QFileInfo::exists(toolchainPath))
+ continue;
+ searchPaths.push_back(toolchainPath);
+ }
+ }
+ registry.endGroup();
+
+ return searchPaths;
+}
+
+Profile createGccProfile(const QFileInfo &compiler, Settings *settings,
+ const QStringList &toolchainTypes,
+ const QString &profileName)
+{
+ const QString machineName = gccMachineName(compiler);
+
+ if (toolchainTypes.contains(QLatin1String("mingw"))) {
+ if (!validMinGWMachines().contains(machineName)) {
+ throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.")
+ .arg(machineName));
+ }
+ }
+
+ Profile profile(!profileName.isEmpty() ? profileName : machineName, settings);
+ profile.removeProfile();
+
+ const ToolchainDetails details(compiler);
+
+ setCommonProperties(profile, compiler, toolchainTypes, details);
+
+ if (!toolchainTypes.contains(QLatin1String("clang"))) {
+ // Check whether auxiliary tools reside within the toolchain's install path.
+ // This might not be the case when using icecc or another compiler wrapper.
+ const QString compilerDirPath = compiler.absolutePath();
+ const ToolPathSetup toolPathSetup(&profile, compilerDirPath, details);
+ toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath"));
+ toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath"));
+ toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath"));
+ if (doesProfileTargetOS(profile, QStringLiteral("darwin")))
+ toolPathSetup.apply(QStringLiteral("dsymutil"),
+ QStringLiteral("cpp.dsymutilPath"));
+ else
+ toolPathSetup.apply(QStringLiteral("objcopy"),
+ QStringLiteral("cpp.objcopyPath"));
+ toolPathSetup.apply(QStringLiteral("strip"),
+ QStringLiteral("cpp.stripPath"));
+ }
+
+ qbsInfo() << Tr::tr("Profile '%1' created for '%2'.")
+ .arg(profile.name(), compiler.absoluteFilePath());
+ return profile;
+}
+
+void gccProbe(Settings *settings, QList<Profile> &profiles, const QString &compilerName)
+{
+ qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName);
+
+ QStringList searchPaths;
+ searchPaths << systemSearchPaths() << gnuRegistrySearchPaths()
+ << atmelRegistrySearchPaths();
+
+ std::vector<QFileInfo> candidates;
+ const auto filters = buildCompilerNameFilters(compilerName);
+ for (const auto &searchPath : searchPaths) {
+ const QDir dir(searchPath);
+ const QStringList fileNames = dir.entryList(
+ filters, QDir::Files | QDir::Executable);
+ for (const QString &fileName : fileNames) {
+ // Ignore unexpected compiler names.
+ if (fileName.startsWith(QLatin1String("c89-gcc"))
+ || fileName.startsWith(QLatin1String("c99-gcc"))) {
+ continue;
+ }
+ const QFileInfo candidate = dir.filePath(fileName);
+ // Filter duplicates.
+ const auto existingEnd = candidates.end();
+ const auto existingIt = std::find_if(
+ candidates.begin(), existingEnd,
+ [candidate](const QFileInfo &existing) {
+ return isSameExecutable(candidate.absoluteFilePath(),
+ existing.absoluteFilePath());
+ });
+ if (existingIt == existingEnd) {
+ // No duplicates are found, just add a new candidate.
+ candidates.push_back(candidate);
+ } else {
+ // Replace the existing entry if a candidate name more than
+ // an existing name.
+ const auto candidateName = candidate.completeBaseName();
+ const auto existingName = existingIt->completeBaseName();
+ if (candidateName > existingName)
+ *existingIt = candidate;
+ }
+ }
+ }
+
+ if (candidates.empty()) {
+ qbsInfo() << Tr::tr("No %1 toolchains found.").arg(compilerName);
+ return;
+ }
+
+ for (const auto &candidate : qAsConst(candidates)) {
+ const QStringList toolchainTypes = toolchainTypeFromCompilerName(
+ candidate.baseName());
+ const QString profileName = buildProfileName(candidate);
+ auto profile = createGccProfile(candidate, settings,
+ toolchainTypes, profileName);
+ profiles.push_back(std::move(profile));
+ }
+}
diff --git a/src/app/qbs-setup-toolchains/gccprobe.h b/src/app/qbs-setup-toolchains/gccprobe.h
new file mode 100644
index 000000000..4344c5836
--- /dev/null
+++ b/src/app/qbs-setup-toolchains/gccprobe.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_SETUPTOOLCHAINS_GCCPROBE_H
+#define QBS_SETUPTOOLCHAINS_GCCPROBE_H
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+class QFileInfo;
+QT_END_NAMESPACE
+
+namespace qbs {
+class Profile;
+class Settings;
+}
+
+qbs::Profile createGccProfile(const QFileInfo &compiler,
+ qbs::Settings *settings,
+ const QStringList &toolchainTypes,
+ const QString &profileName = QString());
+
+void gccProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles,
+ const QString &compilerName);
+
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.cpp b/src/app/qbs-setup-toolchains/iarewprobe.cpp
index 5d3785759..4a8ed499b 100644
--- a/src/app/qbs-setup-toolchains/iarewprobe.cpp
+++ b/src/app/qbs-setup-toolchains/iarewprobe.cpp
@@ -47,9 +47,9 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qstandardpaths.h>
using namespace qbs;
using Internal::Tr;
@@ -57,7 +57,8 @@ using Internal::HostOsInfo;
static QStringList knownIarCompilerNames()
{
- return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), QStringLiteral("iccavr")};
+ return {QStringLiteral("icc8051"), QStringLiteral("iccarm"),
+ QStringLiteral("iccavr"), QStringLiteral("iccstm8")};
}
static QString guessIarArchitecture(const QFileInfo &compiler)
@@ -69,17 +70,29 @@ static QString guessIarArchitecture(const QFileInfo &compiler)
return QStringLiteral("arm");
if (baseName == QLatin1String("iccavr"))
return QStringLiteral("avr");
+ if (baseName == QLatin1String("iccstm8"))
+ return QStringLiteral("stm8");
return {};
}
-static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *settings,
+static Profile createIarProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
QString profileName = QString())
{
+ const QFileInfo compiler = info.compilerPath;
const QString architecture = guessIarArchitecture(compiler);
// In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("iar-") + architecture;
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("iar-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("iar-%1-%2").arg(
+ version, architecture);
+ }
+ }
Profile profile(profileName, settings);
profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath());
@@ -92,9 +105,52 @@ static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *setti
return profile;
}
-static std::vector<IarInstallInfo> installedIarsFromPath()
+static Version dumpIarCompilerVersion(const QFileInfo &compiler)
+{
+ const QString outFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation)
+ + QLatin1String("/macros.dump");
+ const QStringList args = {QStringLiteral("."),
+ QStringLiteral("--predef_macros"),
+ outFilePath};
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), args);
+ p.waitForFinished(3000);
+ const auto es = p.exitStatus();
+ if (es != QProcess::NormalExit) {
+ const QByteArray out = p.readAll();
+ qbsWarning() << Tr::tr("Compiler dumping failed:\n%1")
+ .arg(QString::fromUtf8(out));
+ return Version{};
+ }
+
+ QByteArray dump;
+ QFile out(outFilePath);
+ if (out.open(QIODevice::ReadOnly))
+ dump = out.readAll();
+ out.remove();
+
+ const int verCode = extractVersion(dump, "__VER__ ");
+ if (verCode < 0) {
+ qbsWarning() << Tr::tr("No '__VER__' token was found in a compiler dump:\n%1")
+ .arg(QString::fromUtf8(dump));
+ return Version{};
+ }
+
+ const QString arch = guessIarArchitecture(compiler);
+ if (arch == QLatin1String("arm")) {
+ return Version{verCode / 1000000, (verCode / 1000) % 1000, verCode % 1000};
+ } else if (arch == QLatin1String("avr")
+ || arch == QLatin1String("mcs51")
+ || arch == QLatin1String("stm8")) {
+ return Version{verCode / 100, verCode % 100};
+ }
+
+ return Version{};
+}
+
+static std::vector<ToolchainInstallInfo> installedIarsFromPath()
{
- std::vector<IarInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownIarCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo iarPath(
@@ -102,14 +158,16 @@ static std::vector<IarInstallInfo> installedIarsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!iarPath.exists())
continue;
- infos.push_back({iarPath.absoluteFilePath(), {}});
+ const Version version = dumpIarCompilerVersion(iarPath);
+ infos.push_back({iarPath, version});
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
-static std::vector<IarInstallInfo> installedIarsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedIarsFromRegistry()
{
- std::vector<IarInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -127,6 +185,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
{QStringLiteral("EWARM"), QStringLiteral("\\arm\\bin\\iccarm.exe")},
{QStringLiteral("EWAVR"), QStringLiteral("\\avr\\bin\\iccavr.exe")},
{QStringLiteral("EW8051"), QStringLiteral("\\8051\\bin\\icc8051.exe")},
+ {QStringLiteral("EWSTM8"), QStringLiteral("\\stm8\\bin\\iccstm8.exe")},
};
QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat);
@@ -148,7 +207,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
if (iarPath.exists()) {
// Note: threeLevelKey is a guessed toolchain version.
const QString version = threeLevelKey;
- infos.push_back({iarPath.absoluteFilePath(), version});
+ infos.push_back({iarPath, Version::fromString(version)});
}
}
registry.endGroup();
@@ -161,6 +220,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -175,19 +235,25 @@ bool isIarCompiler(const QString &compilerName)
void createIarProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createIarProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createIarProfileHelper(info, settings, profileName);
}
void iarProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect IAR toolchains...");
- std::vector<IarInstallInfo> allInfos = installedIarsFromRegistry();
- const std::vector<IarInstallInfo> pathInfos = installedIarsFromPath();
- allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
+ // Make sure that a returned infos are sorted before using the std::set_union!
+ const std::vector<ToolchainInstallInfo> regInfos = installedIarsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedIarsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos;
+ allInfos.reserve(regInfos.size() + pathInfos.size());
+ std::set_union(regInfos.cbegin(), regInfos.cend(),
+ pathInfos.cbegin(), pathInfos.cend(),
+ std::back_inserter(allInfos));
- for (const IarInstallInfo &info : allInfos) {
- const auto profile = createIarProfileHelper(info.compilerPath, settings);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto profile = createIarProfileHelper(info, settings);
profiles.push_back(profile);
}
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.h b/src/app/qbs-setup-toolchains/iarewprobe.h
index f5caf61ed..b604d6c6b 100644
--- a/src/app/qbs-setup-toolchains/iarewprobe.h
+++ b/src/app/qbs-setup-toolchains/iarewprobe.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef IAREWPROBE_H
-#define IAREWPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_IAREWPROBE_H
+#define QBS_SETUPTOOLCHAINS_IAREWPROBE_H
#include <QtCore/qlist.h>
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct IarInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isIarCompiler(const QString &compilerName);
void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings,
@@ -64,4 +58,4 @@ void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings,
void iarProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // IAREWPROBE_H
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/keilprobe.cpp b/src/app/qbs-setup-toolchains/keilprobe.cpp
index dc327d2ee..08f0f2167 100644
--- a/src/app/qbs-setup-toolchains/keilprobe.cpp
+++ b/src/app/qbs-setup-toolchains/keilprobe.cpp
@@ -47,9 +47,9 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qtemporaryfile.h>
using namespace qbs;
using Internal::Tr;
@@ -70,14 +70,24 @@ static QString guessKeilArchitecture(const QFileInfo &compiler)
return {};
}
-static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *settings,
+static Profile createKeilProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
QString profileName = QString())
{
+ const QFileInfo compiler = info.compilerPath;
const QString architecture = guessKeilArchitecture(compiler);
// In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("keil-") + architecture;
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("keil-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("keil-%1-%2").arg(
+ version, architecture);
+ }
+ }
Profile profile(profileName, settings);
profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath());
@@ -90,9 +100,80 @@ static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *sett
return profile;
}
-static std::vector<KeilInstallInfo> installedKeilsFromPath()
+static Version dumpKeilCompilerVersion(const QFileInfo &compiler)
+{
+ const QString arch = guessKeilArchitecture(compiler);
+ if (arch == QLatin1String("mcs51")) {
+ QTemporaryFile fakeIn;
+ if (!fakeIn.open()) {
+ qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2")
+ .arg(fakeIn.fileName(), fakeIn.errorString());
+ return Version{};
+ }
+ fakeIn.write("#define VALUE_TO_STRING(x) #x\n");
+ fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n");
+ fakeIn.write("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)\n");
+ fakeIn.write("#ifdef __C51__\n");
+ fakeIn.write("#pragma message(VAR_NAME_VALUE(__C51__))\n");
+ fakeIn.write("#endif\n");
+ fakeIn.write("#ifdef __CX51__\n");
+ fakeIn.write("#pragma message(VAR_NAME_VALUE(__CX51__))\n");
+ fakeIn.write("#endif\n");
+ fakeIn.close();
+
+ const QStringList args = {fakeIn.fileName()};
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), args);
+ p.waitForFinished(3000);
+ const auto es = p.exitStatus();
+ if (es != QProcess::NormalExit) {
+ const QByteArray out = p.readAll();
+ qbsWarning() << Tr::tr("Compiler dumping failed:\n%1")
+ .arg(QString::fromUtf8(out));
+ return Version{};
+ }
+
+ const QByteArray dump = p.readAllStandardOutput();
+ const int verCode = extractVersion(dump, "\"__C51__\"|\"");
+ if (verCode < 0) {
+ qbsWarning() << Tr::tr("No '__C51__' token was found"
+ " in the compiler dump:\n%1")
+ .arg(QString::fromUtf8(dump));
+ return Version{};
+ }
+ return Version{verCode / 100, verCode % 100};
+ } else if (arch == QLatin1String("arm")) {
+ const QStringList args = {QStringLiteral("-E"),
+ QStringLiteral("--list-macros"),
+ QStringLiteral("nul")};
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), args);
+ p.waitForFinished(3000);
+ const auto es = p.exitStatus();
+ if (es != QProcess::NormalExit) {
+ const QByteArray out = p.readAll();
+ qbsWarning() << Tr::tr("Compiler dumping failed:\n%1")
+ .arg(QString::fromUtf8(out));
+ return Version{};
+ }
+
+ const QByteArray dump = p.readAll();
+ const int verCode = extractVersion(dump, "__ARMCC_VERSION ");
+ if (verCode < 0) {
+ qbsWarning() << Tr::tr("No '__ARMCC_VERSION' token was found "
+ "in the compiler dump:\n%1")
+ .arg(QString::fromUtf8(dump));
+ return Version{};
+ }
+ return Version{verCode / 1000000, (verCode / 10000) % 100, verCode % 10000};
+ }
+
+ return Version{};
+}
+
+static std::vector<ToolchainInstallInfo> installedKeilsFromPath()
{
- std::vector<KeilInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownKeilCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo keilPath(
@@ -100,14 +181,16 @@ static std::vector<KeilInstallInfo> installedKeilsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!keilPath.exists())
continue;
- infos.push_back({keilPath.absoluteFilePath(), {}});
+ const Version version = dumpKeilCompilerVersion(keilPath);
+ infos.push_back({keilPath, version});
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
-static std::vector<KeilInstallInfo> installedKeilsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedKeilsFromRegistry()
{
- std::vector<KeilInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -148,7 +231,7 @@ static std::vector<KeilInstallInfo> installedKeilsFromRegistry()
.toString();
if (version.startsWith(QLatin1Char('V')))
version.remove(0, 1);
- infos.push_back({keilPath.absoluteFilePath(), version});
+ infos.push_back({keilPath, Version::fromString(version)});
}
}
registry.endGroup();
@@ -156,6 +239,7 @@ static std::vector<KeilInstallInfo> installedKeilsFromRegistry()
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -170,19 +254,25 @@ bool isKeilCompiler(const QString &compilerName)
void createKeilProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createKeilProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createKeilProfileHelper(info, settings, profileName);
}
void keilProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect KEIL toolchains...");
- std::vector<KeilInstallInfo> allInfos = installedKeilsFromRegistry();
- const std::vector<KeilInstallInfo> pathInfos = installedKeilsFromPath();
- allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
+ // Make sure that a returned infos are sorted before using the std::set_union!
+ const std::vector<ToolchainInstallInfo> regInfos = installedKeilsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedKeilsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos;
+ allInfos.reserve(regInfos.size() + pathInfos.size());
+ std::set_union(regInfos.cbegin(), regInfos.cend(),
+ pathInfos.cbegin(), pathInfos.cend(),
+ std::back_inserter(allInfos));
- for (const KeilInstallInfo &info : allInfos) {
- const auto profile = createKeilProfileHelper(info.compilerPath, settings);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto profile = createKeilProfileHelper(info, settings);
profiles.push_back(profile);
}
diff --git a/src/app/qbs-setup-toolchains/keilprobe.h b/src/app/qbs-setup-toolchains/keilprobe.h
index 6a897b84b..c7e66ee24 100644
--- a/src/app/qbs-setup-toolchains/keilprobe.h
+++ b/src/app/qbs-setup-toolchains/keilprobe.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef KEILPROBE_H
-#define KEILPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_KEILPROBE_H
+#define QBS_SETUPTOOLCHAINS_KEILPROBE_H
#include <QtCore/qlist.h>
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct KeilInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isKeilCompiler(const QString &compilerName);
void createKeilProfile(const QFileInfo &compiler, qbs::Settings *settings,
@@ -64,4 +58,4 @@ void createKeilProfile(const QFileInfo &compiler, qbs::Settings *settings,
void keilProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // KEILPROBE_H
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/msvcprobe.cpp b/src/app/qbs-setup-toolchains/msvcprobe.cpp
index d0b60a7fe..c8108bfd2 100644
--- a/src/app/qbs-setup-toolchains/msvcprobe.cpp
+++ b/src/app/qbs-setup-toolchains/msvcprobe.cpp
@@ -464,9 +464,10 @@ void msvcProbe(Settings *settings, QList<Profile> &profiles)
}
}
-void createMsvcProfile(const QString &profileName, const QString &compilerFilePath,
- Settings *settings)
+void createMsvcProfile(const QFileInfo &compiler, Settings *settings,
+ const QString &profileName)
{
+ const auto compilerFilePath = compiler.absoluteFilePath();
MSVC msvc(compilerFilePath, MSVC::architectureFromClPath(compilerFilePath));
msvc.init();
QList<Profile> dummy;
diff --git a/src/app/qbs-setup-toolchains/msvcprobe.h b/src/app/qbs-setup-toolchains/msvcprobe.h
index 4fa2cde48..f63dd5dc8 100644
--- a/src/app/qbs-setup-toolchains/msvcprobe.h
+++ b/src/app/qbs-setup-toolchains/msvcprobe.h
@@ -37,13 +37,17 @@
**
****************************************************************************/
-#ifndef MSVCPROBE_H
-#define MSVCPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_MSVCPROBE_H
+#define QBS_SETUPTOOLCHAINS_MSVCPROBE_H
#include <QtCore/qlist.h>
#include <vector>
+QT_BEGIN_NAMESPACE
+class QFileInfo;
+QT_END_NAMESPACE
+
namespace qbs {
class Profile;
class Settings;
@@ -59,9 +63,9 @@ struct MSVCInstallInfo
std::vector<MSVCInstallInfo> installedMSVCs();
-void createMsvcProfile(const QString &profileName, const QString &compilerFilePath,
- qbs::Settings *settings);
+void createMsvcProfile(const QFileInfo &compiler, qbs::Settings *settings,
+ const QString &profileName);
void msvcProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // MSVCPROBE_H
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index 3fae20a6e..f041568a9 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -39,6 +39,7 @@
#include "probe.h"
#include "clangclprobe.h"
+#include "gccprobe.h"
#include "iarewprobe.h"
#include "keilprobe.h"
#include "msvcprobe.h"
@@ -46,22 +47,26 @@
#include "xcodeprobe.h"
#include <logging/translator.h>
-#include <tools/architectures.h>
#include <tools/error.h>
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <tools/qttools.h>
#include <tools/settings.h>
#include <tools/toolchains.h>
-#include <tools/stlutils.h>
#include <QtCore/qdir.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qprocess.h>
-#include <QtCore/qstringlist.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qtextstream.h>
-#include <cstdio>
+#ifdef Q_OS_WIN
+// We need defines for Windows 8.
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_WIN8
+
+#include <qt_windows.h>
+#include <ShlObj.h>
+#else
+#include <qplatformdefs.h>
+#endif // Q_OS_WIN
using namespace qbs;
using Internal::HostOsInfo;
@@ -70,6 +75,11 @@ using Internal::Tr;
static QTextStream qStdout(stdout);
static QTextStream qStderr(stderr);
+QStringList systemSearchPaths()
+{
+ return QString::fromLocal8Bit(qgetenv("PATH")).split(HostOsInfo::pathListSeparator());
+}
+
QString findExecutable(const QString &fileName)
{
QString fullFileName = fileName;
@@ -77,8 +87,7 @@ QString findExecutable(const QString &fileName)
&& !fileName.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive)) {
fullFileName += QLatin1String(".exe");
}
- const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
- const auto ppaths = path.split(HostOsInfo::pathListSeparator());
+ const auto ppaths = systemSearchPaths();
for (const QString &ppath : ppaths) {
const QString fullPath = ppath + QLatin1Char('/') + fullFileName;
if (QFileInfo::exists(fullPath))
@@ -87,31 +96,7 @@ QString findExecutable(const QString &fileName)
return {};
}
-static QString qsystem(const QString &exe, const QStringList &args = QStringList())
-{
- QProcess p;
- p.setProcessChannelMode(QProcess::MergedChannels);
- p.start(exe, args);
- if (!p.waitForStarted()) {
- throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2")
- .arg(exe, p.errorString()));
- }
- if (!p.waitForFinished(-1) || p.exitCode() != 0)
- throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2").arg(exe, p.errorString()));
- return QString::fromLocal8Bit(p.readAll());
-}
-
-static QStringList validMinGWMachines()
-{
- // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs
- return {QStringLiteral("mingw32"), QStringLiteral("mingw64"),
- QStringLiteral("i686-w64-mingw32"), QStringLiteral("x86_64-w64-mingw32"),
- QStringLiteral("i686-w64-mingw32.shared"), QStringLiteral("x86_64-w64-mingw32.shared"),
- QStringLiteral("i686-w64-mingw32.static"), QStringLiteral("x86_64-w64-mingw32.static"),
- QStringLiteral("i586-mingw32msvc"), QStringLiteral("amd64-mingw32msvc")};
-}
-
-static QStringList toolchainTypeFromCompilerName(const QString &compilerName)
+QStringList toolchainTypeFromCompilerName(const QString &compilerName)
{
if (compilerName == QLatin1String("cl.exe"))
return canonicalToolchain(QStringLiteral("msvc"));
@@ -134,174 +119,19 @@ static QStringList toolchainTypeFromCompilerName(const QString &compilerName)
return {};
}
-static QString gccMachineName(const QString &compilerFilePath)
-{
- return qsystem(compilerFilePath, QStringList() << QStringLiteral("-dumpmachine")).trimmed();
-}
-
-static QStringList standardCompilerFileNames()
-{
- return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")),
- HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")),
- HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")),
- HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))};
-}
-
-static void setCommonProperties(Profile &profile, const QString &compilerFilePath,
- const QStringList &toolchainTypes)
-{
- const QFileInfo cfi(compilerFilePath);
- const QString compilerName = cfi.fileName();
-
- if (toolchainTypes.contains(QStringLiteral("mingw")))
- profile.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows"));
-
- const QString prefix = compilerName.left(compilerName.lastIndexOf(QLatin1Char('-')) + 1);
- if (!prefix.isEmpty())
- profile.setValue(QStringLiteral("cpp.toolchainPrefix"), prefix);
-
- profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), cfi.absolutePath());
- profile.setValue(QStringLiteral("qbs.toolchain"), toolchainTypes);
-
- const QString suffix = compilerName.right(compilerName.size() - prefix.size());
- if (!standardCompilerFileNames().contains(suffix))
- qWarning("%s", qPrintable(
- QStringLiteral("'%1' is not a standard compiler file name; "
- "you must set the cpp.cCompilerName and "
- "cpp.cxxCompilerName properties of this profile "
- "manually").arg(compilerName)));
-}
-
-class ToolPathSetup
-{
-public:
- ToolPathSetup(Profile *profile, QString path, QString toolchainPrefix)
- : m_profile(profile),
- m_compilerDirPath(std::move(path)),
- m_toolchainPrefix(std::move(toolchainPrefix))
- {
- }
-
- void apply(const QString &toolName, const QString &propertyName) const
- {
- QString toolFileName = m_toolchainPrefix + HostOsInfo::appendExecutableSuffix(toolName);
- if (QFile::exists(m_compilerDirPath + QLatin1Char('/') + toolFileName))
- return;
- const QString toolFilePath = findExecutable(toolFileName);
- if (toolFilePath.isEmpty()) {
- qWarning("%s", qPrintable(QStringLiteral("'%1' exists neither in '%2' nor in PATH.")
- .arg(toolFileName, m_compilerDirPath)));
- }
- m_profile->setValue(propertyName, toolFilePath);
- }
-
-private:
- Profile * const m_profile;
- QString m_compilerDirPath;
- QString m_toolchainPrefix;
-};
-
-static bool doesProfileTargetOS(const Profile &profile, const QString &os)
-{
- const auto target = profile.value(QStringLiteral("qbs.targetPlatform"));
- if (target.isValid()) {
- return Internal::contains(HostOsInfo::canonicalOSIdentifiers(
- target.toString().toStdString()), os.toStdString());
- }
- return Internal::contains(HostOsInfo::hostOSIdentifiers(), os.toStdString());
-}
-
-static Profile createGccProfile(const QString &compilerFilePath, Settings *settings,
- const QStringList &toolchainTypes,
- const QString &profileName = QString())
-{
- const QString machineName = gccMachineName(compilerFilePath);
-
- if (toolchainTypes.contains(QLatin1String("mingw"))) {
- if (!validMinGWMachines().contains(machineName)) {
- throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.")
- .arg(machineName));
- }
- }
-
- Profile profile(!profileName.isEmpty() ? profileName : machineName, settings);
- profile.removeProfile();
- setCommonProperties(profile, compilerFilePath, toolchainTypes);
-
- // Check whether auxiliary tools reside within the toolchain's install path.
- // This might not be the case when using icecc or another compiler wrapper.
- const QString compilerDirPath = QFileInfo(compilerFilePath).absolutePath();
- const ToolPathSetup toolPathSetup(&profile, compilerDirPath,
- profile.value(QStringLiteral("cpp.toolchainPrefix"))
- .toString());
- toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath"));
- toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath"));
- toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath"));
- if (doesProfileTargetOS(profile, QStringLiteral("darwin")))
- toolPathSetup.apply(QStringLiteral("dsymutil"), QStringLiteral("cpp.dsymutilPath"));
- else
- toolPathSetup.apply(QStringLiteral("objcopy"), QStringLiteral("cpp.objcopyPath"));
- toolPathSetup.apply(QStringLiteral("strip"), QStringLiteral("cpp.stripPath"));
-
- qStdout << Tr::tr("Profile '%1' created for '%2'.").arg(profile.name(), compilerFilePath)
- << endl;
- return profile;
-}
-
-static void gccProbe(Settings *settings, QList<Profile> &profiles, const QString &compilerName)
-{
- qStdout << Tr::tr("Trying to detect %1...").arg(compilerName) << endl;
-
- const QString crossCompilePrefix = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE"));
- const QString compilerFilePath = findExecutable(crossCompilePrefix + compilerName);
- QFileInfo cfi(compilerFilePath);
- if (!cfi.exists()) {
- qStderr << Tr::tr("%1 not found.").arg(compilerName) << endl;
- return;
- }
- const QString profileName = cfi.completeBaseName();
- const QStringList toolchainTypes = toolchainTypeFromCompilerName(compilerName);
- profiles.push_back(createGccProfile(compilerFilePath, settings, toolchainTypes, profileName));
-}
-
-static void mingwProbe(Settings *settings, QList<Profile> &profiles)
-{
- // List of possible compiler binary names for this platform
- QStringList compilerNames;
- if (HostOsInfo::isWindowsHost()) {
- compilerNames << QStringLiteral("gcc");
- } else {
- const auto machineNames = validMinGWMachines();
- for (const QString &machineName : machineNames) {
- compilerNames << machineName + QLatin1String("-gcc");
- }
- }
-
- for (const QString &compilerName : qAsConst(compilerNames)) {
- const QString gccPath
- = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName));
- if (!gccPath.isEmpty())
- profiles.push_back(createGccProfile(gccPath, settings,
- canonicalToolchain(QStringLiteral("mingw"))));
- }
-}
-
void probe(Settings *settings)
{
QList<Profile> profiles;
if (HostOsInfo::isWindowsHost()) {
msvcProbe(settings, profiles);
clangClProbe(settings, profiles);
- } else {
- gccProbe(settings, profiles, QStringLiteral("gcc"));
- gccProbe(settings, profiles, QStringLiteral("clang"));
-
- if (HostOsInfo::isMacosHost()) {
- xcodeProbe(settings, profiles);
- }
+ } else if (HostOsInfo::isMacosHost()) {
+ xcodeProbe(settings, profiles);
}
- mingwProbe(settings, profiles);
+ gccProbe(settings, profiles, QStringLiteral("gcc"));
+ gccProbe(settings, profiles, QStringLiteral("clang"));
+
iarProbe(settings, profiles);
keilProbe(settings, profiles);
sdccProbe(settings, profiles);
@@ -334,11 +164,11 @@ void createProfile(const QString &profileName, const QString &toolchainType,
toolchainTypes = canonicalToolchain(toolchainType);
if (toolchainTypes.contains(QLatin1String("msvc")))
- createMsvcProfile(profileName, compiler.absoluteFilePath(), settings);
+ createMsvcProfile(compiler, settings, profileName);
else if (toolchainTypes.contains(QLatin1String("clang-cl")))
- createClangClProfile(profileName, compiler.absoluteFilePath(), settings);
+ createClangClProfile(compiler, settings, profileName);
else if (toolchainTypes.contains(QLatin1String("gcc")))
- createGccProfile(compiler.absoluteFilePath(), settings, toolchainTypes, profileName);
+ createGccProfile(compiler, settings, toolchainTypes, profileName);
else if (toolchainTypes.contains(QLatin1String("iar")))
createIarProfile(compiler, settings, profileName);
else if (toolchainTypes.contains(QLatin1String("keil")))
@@ -348,3 +178,126 @@ void createProfile(const QString &profileName, const QString &toolchainType,
else
throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type."));
}
+
+int extractVersion(const QByteArray &macroDump, const QByteArray &keyToken)
+{
+ const int startIndex = macroDump.indexOf(keyToken);
+ if (startIndex == -1)
+ return -1;
+ const int endIndex = macroDump.indexOf('\n', startIndex);
+ if (endIndex == -1)
+ return -1;
+ const auto keyLength = keyToken.length();
+ const int version = macroDump.mid(startIndex + keyLength,
+ endIndex - startIndex - keyLength)
+ .toInt();
+ return version;
+}
+
+static QString resolveSymlinks(const QString &filePath)
+{
+ QFileInfo fi(filePath);
+ int links = 16;
+ while (links-- && fi.isSymLink())
+ fi.setFile(fi.dir(), fi.symLinkTarget());
+ if (links <= 0)
+ return {};
+ return fi.filePath();
+}
+
+// Copied from qfilesystemengine_win.cpp.
+#ifdef Q_OS_WIN
+
+// File ID for Windows up to version 7.
+static inline QByteArray fileIdWin7(HANDLE handle)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ if (GetFileInformationByHandle(handle, &info)) {
+ char buffer[sizeof "01234567:0123456701234567\0"];
+ qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx",
+ info.dwVolumeSerialNumber,
+ info.nFileIndexHigh,
+ info.nFileIndexLow);
+ return QByteArray(buffer);
+ }
+ return {};
+}
+
+// File ID for Windows starting from version 8.
+static QByteArray fileIdWin8(HANDLE handle)
+{
+ QByteArray result;
+ FILE_ID_INFO infoEx = {};
+ if (::GetFileInformationByHandleEx(
+ handle,
+ static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8
+ &infoEx, sizeof(FILE_ID_INFO))) {
+ result = QByteArray::number(infoEx.VolumeSerialNumber, 16);
+ result += ':';
+ // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one.
+ result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId),
+ int(sizeof(infoEx.FileId))).toHex();
+ }
+ return result;
+}
+
+static QByteArray fileIdWin(HANDLE fHandle)
+{
+ return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8
+ ? fileIdWin8(HANDLE(fHandle))
+ : fileIdWin7(HANDLE(fHandle));
+}
+
+static QByteArray fileId(const QString &filePath)
+{
+ QByteArray result;
+ const HANDLE handle = ::CreateFile(
+ reinterpret_cast<const wchar_t*>(filePath.utf16()), 0,
+ FILE_SHARE_READ, nullptr, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (handle != INVALID_HANDLE_VALUE) {
+ result = fileIdWin(handle);
+ ::CloseHandle(handle);
+ }
+ return result;
+}
+
+static qint64 fileSize(const QString &filePath)
+{
+ return QFileInfo(filePath).size();
+}
+
+#else
+
+static QByteArray fileId(const QString &filePath)
+{
+ QByteArray result;
+ if (Q_UNLIKELY(filePath.isEmpty()))
+ return {};
+ QT_STATBUF statResult = {};
+ if (QT_STAT(filePath.toLocal8Bit().constData(), &statResult))
+ return {};
+ result = QByteArray::number(quint64(statResult.st_dev), 16);
+ result += ':';
+ result += QByteArray::number(quint64(statResult.st_ino));
+ return result;
+}
+
+#endif // Q_OS_WIN
+
+bool isSameExecutable(const QString &filePath1, const QString &filePath2)
+{
+ if (filePath1 == filePath2)
+ return true;
+ if (resolveSymlinks(filePath1) == resolveSymlinks(filePath2))
+ return true;
+ if (fileId(filePath1) == fileId(filePath2))
+ return true;
+
+#ifdef Q_OS_WIN
+ if (fileSize(filePath1) == fileSize(filePath2))
+ return true;
+#endif
+
+ return false;
+}
diff --git a/src/app/qbs-setup-toolchains/probe.h b/src/app/qbs-setup-toolchains/probe.h
index 510747ef7..235d7a899 100644
--- a/src/app/qbs-setup-toolchains/probe.h
+++ b/src/app/qbs-setup-toolchains/probe.h
@@ -36,10 +36,15 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QBS_PROBE_H
-#define QBS_PROBE_H
-#include <QtCore/qglobal.h>
+#ifndef QBS_SETUPTOOLCHAINS_PROBE_H
+#define QBS_SETUPTOOLCHAINS_PROBE_H
+
+#include <tools/version.h>
+
+#include <QtCore/qfileinfo.h>
+
+#include <tuple> // for std::tie
QT_BEGIN_NAMESPACE
class QString;
@@ -48,11 +53,32 @@ QT_END_NAMESPACE
namespace qbs { class Settings; }
+QStringList systemSearchPaths();
+
QString findExecutable(const QString &fileName);
+QStringList toolchainTypeFromCompilerName(const QString &compilerName);
+
void createProfile(const QString &profileName, const QString &toolchainType,
const QString &compilerFilePath, qbs::Settings *settings);
void probe(qbs::Settings *settings);
+struct ToolchainInstallInfo
+{
+ QFileInfo compilerPath;
+ qbs::Version compilerVersion;
+};
+
+inline bool operator<(const ToolchainInstallInfo &lhs, const ToolchainInstallInfo &rhs)
+{
+ const auto lp = lhs.compilerPath.absoluteFilePath();
+ const auto rp = rhs.compilerPath.absoluteFilePath();
+ return std::tie(lp, lhs.compilerVersion) < std::tie(rp, rhs.compilerVersion);
+}
+
+int extractVersion(const QByteArray &macroDump, const QByteArray &keyToken);
+
+bool isSameExecutable(const QString &exe1, const QString &exe2);
+
#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
index e83a9c716..6581bec63 100644
--- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
+++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro
@@ -5,6 +5,7 @@ TARGET = qbs-setup-toolchains
HEADERS += \
clangclprobe.h \
commandlineparser.h \
+ gccprobe.h \
iarewprobe.h \
keilprobe.h \
msvcprobe.h \
@@ -15,6 +16,7 @@ HEADERS += \
SOURCES += \
clangclprobe.cpp \
commandlineparser.cpp \
+ gccprobe.cpp \
iarewprobe.cpp \
keilprobe.cpp \
main.cpp \
diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
index fd3043a28..554891fc4 100644
--- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
+++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs
@@ -8,6 +8,8 @@ QbsApp {
"clangclprobe.h",
"commandlineparser.cpp",
"commandlineparser.h",
+ "gccprobe.cpp",
+ "gccprobe.h",
"iarewprobe.cpp",
"iarewprobe.h",
"keilprobe.cpp",
diff --git a/src/app/qbs-setup-toolchains/sdccprobe.cpp b/src/app/qbs-setup-toolchains/sdccprobe.cpp
index 751e872ee..e916a405b 100644
--- a/src/app/qbs-setup-toolchains/sdccprobe.cpp
+++ b/src/app/qbs-setup-toolchains/sdccprobe.cpp
@@ -47,9 +47,9 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qtemporaryfile.h>
using namespace qbs;
using Internal::Tr;
@@ -60,37 +60,119 @@ static QStringList knownSdccCompilerNames()
return {QStringLiteral("sdcc")};
}
-static QString guessSdccArchitecture(const QFileInfo &compiler)
+static QByteArray dumpSdccMacros(const QFileInfo &compiler,
+ const QString &targetFlag = QString())
{
- const auto baseName = compiler.baseName();
- if (baseName == QLatin1String("sdcc"))
- return QStringLiteral("mcs51");
- return {};
+ QTemporaryFile fakeIn(QStringLiteral("XXXXXX.c"));
+ if (!fakeIn.open()) {
+ qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2")
+ .arg(fakeIn.fileName(), fakeIn.errorString());
+ return {};
+ }
+ fakeIn.close();
+
+ const QStringList args = {QStringLiteral("-dM"),
+ QStringLiteral("-E"),
+ targetFlag,
+ fakeIn.fileName()};
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), args);
+ p.waitForFinished(3000);
+ const auto es = p.exitStatus();
+ if (es != QProcess::NormalExit) {
+ const QByteArray out = p.readAll();
+ qbsWarning() << Tr::tr("Compiler dumping failed:\n%1")
+ .arg(QString::fromUtf8(out));
+ return {};
+ }
+
+ return p.readAllStandardOutput();
+}
+
+static QString dumpSdccArchitecture(const QFileInfo &compiler,
+ const QString &arch)
+{
+ const auto targetFlag = QStringLiteral("-m%1").arg(arch);
+ const auto token = QStringLiteral("__SDCC_%1").arg(arch);
+ const auto macros = dumpSdccMacros(compiler, targetFlag);
+ return macros.contains(token.toLatin1()) ? arch : QString();
}
-static Profile createSdccProfileHelper(const QFileInfo &compiler, Settings *settings,
- QString profileName = QString())
+static std::vector<Profile> createSdccProfileHelper(
+ const ToolchainInstallInfo &info,
+ Settings *settings,
+ const QString &profileName = QString())
{
- const QString architecture = guessSdccArchitecture(compiler);
+ const QFileInfo compiler = info.compilerPath;
+
+ std::vector<Profile> profiles;
+
+ const char *knownArchs[] = {"mcs51", "stm8"};
+ for (const auto &knownArch : knownArchs) {
+ const auto actualArch = dumpSdccArchitecture(
+ compiler, QString::fromLatin1(knownArch));
+ // Don't create a profile in case the compiler does
+ // not support the proposed architecture.
+ if (actualArch != QString::fromLatin1(knownArch))
+ continue;
- // In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("sdcc-") + architecture;
+ QString fullProfileName = profileName;
+ if (fullProfileName.isEmpty()) {
+ // Create a full profile name in case we is
+ // in auto-detecting mode.
+ if (!info.compilerVersion.isValid()) {
+ fullProfileName = QStringLiteral("sdcc-unknown-%1")
+ .arg(actualArch);
+ } else {
+ const QString version = info.compilerVersion.toString(
+ QLatin1Char('_'), QLatin1Char('_'));
+ fullProfileName = QStringLiteral("sdcc-%1-%2").arg(
+ version, actualArch);
+ }
+ } else {
+ // Append the detected actual architecture name
+ // to the proposed profile name.
+ fullProfileName = QStringLiteral("%1-%2").arg(
+ fullProfileName, actualArch);
+ }
+
+ Profile profile(fullProfileName, settings);
+ profile.setValue(QStringLiteral("cpp.toolchainInstallPath"),
+ compiler.absolutePath());
+ profile.setValue(QStringLiteral("qbs.toolchainType"),
+ QStringLiteral("sdcc"));
+ if (!actualArch.isEmpty())
+ profile.setValue(QStringLiteral("qbs.architecture"), actualArch);
+
+ qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg(
+ profile.name(), compiler.absoluteFilePath());
+ }
- Profile profile(profileName, settings);
- profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath());
- profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("sdcc"));
- if (!architecture.isEmpty())
- profile.setValue(QStringLiteral("qbs.architecture"), architecture);
+ return profiles;
+}
+
+static Version dumpSdccCompilerVersion(const QFileInfo &compiler)
+{
+ const QByteArray dump = dumpSdccMacros(compiler);
+ if (dump.isEmpty())
+ return Version{};
+
+ const int major = extractVersion(dump, "__SDCC_VERSION_MAJOR ");
+ const int minor = extractVersion(dump, "__SDCC_VERSION_MINOR ");
+ const int patch = extractVersion(dump, "__SDCC_VERSION_PATCH ");
+ if (major < 0 || minor < 0 || patch < 0) {
+ qbsWarning() << Tr::tr("No '__SDCC_VERSION_xxx' token was found "
+ "in the compiler dump:\n%1")
+ .arg(QString::fromUtf8(dump));
+ return Version{};
+ }
- qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg(
- profile.name(), compiler.absoluteFilePath());
- return profile;
+ return Version{major, minor, patch};
}
-static std::vector<SdccInstallInfo> installedSdccsFromPath()
+static std::vector<ToolchainInstallInfo> installedSdccsFromPath()
{
- std::vector<SdccInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownSdccCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo sdccPath(
@@ -98,14 +180,16 @@ static std::vector<SdccInstallInfo> installedSdccsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!sdccPath.exists())
continue;
- infos.push_back({sdccPath.absoluteFilePath(), {}});
+ const Version version = dumpSdccCompilerVersion(sdccPath);
+ infos.push_back({sdccPath, version});
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
-static std::vector<SdccInstallInfo> installedSdccsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedSdccsFromRegistry()
{
- std::vector<SdccInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -126,11 +210,12 @@ static std::vector<SdccInstallInfo> installedSdccsFromRegistry()
registry.value(QStringLiteral("VersionMajor")).toString(),
registry.value(QStringLiteral("VersionMinor")).toString(),
registry.value(QStringLiteral("VersionRevision")).toString());
- infos.push_back({sdccPath.absoluteFilePath(), version});
+ infos.push_back({sdccPath, Version::fromString(version)});
}
}
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -145,20 +230,28 @@ bool isSdccCompiler(const QString &compilerName)
void createSdccProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createSdccProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createSdccProfileHelper(info, settings, profileName);
}
void sdccProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect SDCC toolchains...");
- std::vector<SdccInstallInfo> allInfos = installedSdccsFromRegistry();
- const std::vector<SdccInstallInfo> pathInfos = installedSdccsFromPath();
- allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
+ // Make sure that a returned infos are sorted before using the std::set_union!
+ const std::vector<ToolchainInstallInfo> regInfos = installedSdccsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedSdccsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos;
+ allInfos.reserve(regInfos.size() + pathInfos.size());
+ std::set_union(regInfos.cbegin(), regInfos.cend(),
+ pathInfos.cbegin(), pathInfos.cend(),
+ std::back_inserter(allInfos));
- for (const SdccInstallInfo &info : allInfos) {
- const auto profile = createSdccProfileHelper(info.compilerPath, settings);
- profiles.push_back(profile);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto newProfiles = createSdccProfileHelper(info, settings);
+ profiles.reserve(profiles.size() + int(newProfiles.size()));
+ std::copy(newProfiles.cbegin(), newProfiles.cend(),
+ std::back_inserter(profiles));
}
if (allInfos.empty())
diff --git a/src/app/qbs-setup-toolchains/sdccprobe.h b/src/app/qbs-setup-toolchains/sdccprobe.h
index 7f4219b5a..5fad90e96 100644
--- a/src/app/qbs-setup-toolchains/sdccprobe.h
+++ b/src/app/qbs-setup-toolchains/sdccprobe.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef SDCCPROBE_H
-#define SDCCPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_SDCCPROBE_H
+#define QBS_SETUPTOOLCHAINS_SDCCPROBE_H
#include <QtCore/qlist.h>
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct SdccInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isSdccCompiler(const QString &compilerName);
void createSdccProfile(const QFileInfo &compiler, qbs::Settings *settings,
@@ -64,4 +58,4 @@ void createSdccProfile(const QFileInfo &compiler, qbs::Settings *settings,
void sdccProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // SDCCPROBE_H
+#endif // Header guard
diff --git a/src/app/qbs-setup-toolchains/xcodeprobe.h b/src/app/qbs-setup-toolchains/xcodeprobe.h
index 11fc2bffa..ab501036b 100644
--- a/src/app/qbs-setup-toolchains/xcodeprobe.h
+++ b/src/app/qbs-setup-toolchains/xcodeprobe.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef XCODEPROBE_H
-#define XCODEPROBE_H
+#ifndef QBS_SETUPTOOLCHAINS_XCODEPROBE_H
+#define QBS_SETUPTOOLCHAINS_XCODEPROBE_H
#include <QtCore/qlist.h>
@@ -49,4 +49,4 @@ class Settings;
void xcodeProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles);
-#endif // XCODEPROBE_H
+#endif // Header guard
diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
index 1a1d51f11..16c3621b6 100644
--- a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -58,6 +59,14 @@ AbstractCommandExecutor::AbstractCommandExecutor(Logger logger, QObject *parent)
, m_dryRun(false)
, m_logger(std::move(logger))
{
+ m_watchdog.setSingleShot(true);
+ connect(&m_watchdog, &QTimer::timeout,
+ this, [this]() {
+ cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout.")});
+ });
+ connect(this, &AbstractCommandExecutor::finished,
+ &m_watchdog, &QTimer::stop);
+
}
void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd)
@@ -66,7 +75,8 @@ void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *c
m_command = cmd;
doSetup();
doReportCommandDescription(transformer->product()->fullDisplayName());
- doStart();
+ if (doStart())
+ startTimeout();
}
void AbstractCommandExecutor::doReportCommandDescription(const QString &productName)
@@ -84,5 +94,14 @@ void AbstractCommandExecutor::doReportCommandDescription(const QString &productN
}
}
+void AbstractCommandExecutor::startTimeout()
+{
+ if (!m_dryRun || m_command->ignoreDryRun()) {
+ const auto timeout = m_command->timeout();
+ if (timeout > 0)
+ m_watchdog.start(timeout * 1000);
+ }
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.h b/src/lib/corelib/buildgraph/abstractcommandexecutor.h
index 60b2b40b2..c0f149622 100644
--- a/src/lib/corelib/buildgraph/abstractcommandexecutor.h
+++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -45,6 +46,7 @@
#include <tools/error.h>
#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
namespace qbs {
class ErrorInfo;
@@ -64,7 +66,7 @@ public:
void setDryRunEnabled(bool enabled) { m_dryRun = enabled; }
void setEchoMode(CommandEchoMode echoMode) { m_echoMode = echoMode; }
- virtual void cancel() = 0;
+ virtual void cancel(const qbs::ErrorInfo &reason = {}) = 0;
void start(Transformer *transformer, AbstractCommand *cmd);
@@ -83,7 +85,9 @@ protected:
private:
virtual void doSetup() { };
- virtual void doStart() = 0;
+ virtual bool doStart() = 0;
+
+ void startTimeout();
private:
AbstractCommand *m_command;
@@ -91,6 +95,7 @@ private:
ScriptEngine *m_mainThreadScriptEngine;
bool m_dryRun;
Internal::Logger m_logger;
+ QTimer m_watchdog;
};
} // namespace Internal
diff --git a/src/lib/corelib/buildgraph/jscommandexecutor.cpp b/src/lib/corelib/buildgraph/jscommandexecutor.cpp
index 30970779c..5c83b2056 100644
--- a/src/lib/corelib/buildgraph/jscommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/jscommandexecutor.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -82,9 +83,11 @@ public:
return m_result;
}
- void cancel()
+ void cancel(const qbs::ErrorInfo &reason)
{
QBS_ASSERT(m_scriptEngine, return);
+ m_result.success = !reason.hasError();
+ m_result.errorMessage = reason.toString();
m_scriptEngine->abortEvaluation();
}
@@ -226,24 +229,25 @@ void JsCommandExecutor::waitForFinished()
loop.exec();
}
-void JsCommandExecutor::doStart()
+bool JsCommandExecutor::doStart()
{
- QBS_ASSERT(!m_running, return);
+ QBS_ASSERT(!m_running, return false);
m_thread->start();
if (dryRun() && !command()->ignoreDryRun()) {
QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller.
- return;
+ return false;
}
m_running = true;
emit startRequested(jsCommand(), transformer());
+ return true;
}
-void JsCommandExecutor::cancel()
+void JsCommandExecutor::cancel(const qbs::ErrorInfo &reason)
{
if (m_running && !dryRun())
- QTimer::singleShot(0, m_objectInThread, [this] { m_objectInThread->cancel(); });
+ QTimer::singleShot(0, m_objectInThread, [objectInThread = m_objectInThread, reason] { objectInThread->cancel(reason); });
}
void JsCommandExecutor::onJavaScriptCommandFinished()
diff --git a/src/lib/corelib/buildgraph/jscommandexecutor.h b/src/lib/corelib/buildgraph/jscommandexecutor.h
index 0170c5231..0725f0d24 100644
--- a/src/lib/corelib/buildgraph/jscommandexecutor.h
+++ b/src/lib/corelib/buildgraph/jscommandexecutor.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -65,8 +66,8 @@ private:
void onJavaScriptCommandFinished();
void doReportCommandDescription(const QString &productName) override;
- void doStart() override;
- void cancel() override;
+ bool doStart() override;
+ void cancel(const qbs::ErrorInfo &reason) override;
void waitForFinished();
diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.cpp b/src/lib/corelib/buildgraph/processcommandexecutor.cpp
index c34a734b4..f8a86cfe8 100644
--- a/src/lib/corelib/buildgraph/processcommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/processcommandexecutor.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -119,9 +120,9 @@ void ProcessCommandExecutor::doSetup()
m_shellInvocation = shellQuote(QDir::toNativeSeparators(m_program), m_arguments);
}
-void ProcessCommandExecutor::doStart()
+bool ProcessCommandExecutor::doStart()
{
- QBS_ASSERT(m_process.state() == QProcess::NotRunning, return);
+ QBS_ASSERT(m_process.state() == QProcess::NotRunning, return false);
const ProcessCommand * const cmd = processCommand();
@@ -131,7 +132,7 @@ void ProcessCommandExecutor::doStart()
if (dryRun() && !cmd->ignoreDryRun()) {
QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller.
- return;
+ return false;
}
const QString workingDir = QDir::fromNativeSeparators(cmd->workingDir());
@@ -142,7 +143,7 @@ void ProcessCommandExecutor::doStart()
"is invalid.").arg(QDir::toNativeSeparators(workingDir),
QDir::toNativeSeparators(m_program)),
cmd->codeLocation()));
- return;
+ return false;
}
}
@@ -163,7 +164,7 @@ void ProcessCommandExecutor::doStart()
if (!responseFile.open()) {
emit finished(ErrorInfo(Tr::tr("Cannot create response file '%1'.")
.arg(responseFile.fileName())));
- return;
+ return false;
}
for (int i = cmd->responseFileArgumentIndex(); i < cmd->arguments().size(); ++i) {
const QString arg = cmd->arguments().at(i);
@@ -172,7 +173,7 @@ void ProcessCommandExecutor::doStart()
if (!f.open(QIODevice::ReadOnly)) {
emit finished(ErrorInfo(Tr::tr("Cannot open command file '%1'.")
.arg(QDir::toNativeSeparators(f.fileName()))));
- return;
+ return false;
}
responseFile.write(f.readAll());
} else {
@@ -194,13 +195,15 @@ void ProcessCommandExecutor::doStart()
qCDebug(lcExec) << "Additional environment:" << additionalVariables.toStringList();
m_process.setWorkingDirectory(workingDir);
m_process.start(m_program, arguments);
+ return true;
}
-void ProcessCommandExecutor::cancel()
+void ProcessCommandExecutor::cancel(const qbs::ErrorInfo &reason)
{
// We don't want this command to be reported as failing, since we explicitly terminated it.
disconnect(this, &ProcessCommandExecutor::reportProcessResult, nullptr, nullptr);
+ m_cancelReason = reason;
m_process.cancel();
}
@@ -302,10 +305,13 @@ void ProcessCommandExecutor::sendProcessOutput()
const bool processError = result.error() != QProcess::UnknownError;
const bool failureExit = quint32(m_process.exitCode())
> quint32(processCommand()->maxExitCode());
- result.d->success = !processError && !failureExit;
+ const bool cancelledWithError = m_cancelReason.hasError();
+ result.d->success = !processError && !failureExit && !cancelledWithError;
emit reportProcessResult(result);
- if (Q_UNLIKELY(processError)) {
+ if (Q_UNLIKELY(cancelledWithError)) {
+ emit finished(m_cancelReason);
+ } else if (Q_UNLIKELY(processError)) {
emit finished(ErrorInfo(errorString));
} else if (Q_UNLIKELY(failureExit)) {
emit finished(ErrorInfo(Tr::tr("Process failed with exit code %1.")
@@ -323,6 +329,8 @@ void ProcessCommandExecutor::onProcessError()
QTimer::singleShot(0, this, &ProcessCommandExecutor::onProcessError);
return;
}
+ if (m_cancelReason.hasError())
+ return; // Ignore. Cancel reasons will be handled by on ProcessFinished().
switch (m_process.error()) {
case QProcess::FailedToStart: {
removeResponseFile();
diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.h b/src/lib/corelib/buildgraph/processcommandexecutor.h
index 67eb9f746..b0f955882 100644
--- a/src/lib/corelib/buildgraph/processcommandexecutor.h
+++ b/src/lib/corelib/buildgraph/processcommandexecutor.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -71,8 +72,8 @@ private:
void doSetup() override;
void doReportCommandDescription(const QString &productName) override;
- void doStart() override;
- void cancel() override;
+ bool doStart() override;
+ void cancel(const qbs::ErrorInfo &reason) override;
void startProcessCommand();
QString filterProcessOutput(const QByteArray &output, const QString &filterFunctionSource);
@@ -91,6 +92,7 @@ private:
QProcessEnvironment m_buildEnvironment;
QProcessEnvironment m_commandEnvironment;
QString m_responseFileName;
+ qbs::ErrorInfo m_cancelReason;
};
} // namespace Internal
diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp
index ecbc54292..31ff6be4b 100644
--- a/src/lib/corelib/buildgraph/rulecommands.cpp
+++ b/src/lib/corelib/buildgraph/rulecommands.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -74,6 +75,7 @@ static QString stderrFilePathProperty() { return QStringLiteral("stderrFilePath"
static QString stderrFilterFunctionProperty() { return QStringLiteral("stderrFilterFunction"); }
static QString stdoutFilePathProperty() { return QStringLiteral("stdoutFilePath"); }
static QString stdoutFilterFunctionProperty() { return QStringLiteral("stdoutFilterFunction"); }
+static QString timeoutProperty() { return QStringLiteral("timeout"); }
static QString workingDirProperty() { return QStringLiteral("workingDirectory"); }
static QString invokedSourceCode(const QScriptValue codeOrFunction)
@@ -87,7 +89,8 @@ AbstractCommand::AbstractCommand()
m_extendedDescription(defaultExtendedDescription()),
m_highlight(defaultHighLight()),
m_ignoreDryRun(defaultIgnoreDryRun()),
- m_silent(defaultIsSilent())
+ m_silent(defaultIsSilent()),
+ m_timeout(defaultTimeout())
{
}
@@ -104,6 +107,7 @@ bool AbstractCommand::equals(const AbstractCommand *other) const
&& m_ignoreDryRun == other->m_ignoreDryRun
&& m_silent == other->m_silent
&& m_jobPool == other->m_jobPool
+ && m_timeout == other->m_timeout
&& m_properties == other->m_properties;
}
@@ -115,6 +119,9 @@ void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const
m_ignoreDryRun = scriptValue->property(ignoreDryRunProperty()).toBool();
m_silent = scriptValue->property(silentProperty()).toBool();
m_jobPool = scriptValue->property(StringConstants::jobPoolProperty()).toString();
+ const auto timeoutScriptValue = scriptValue->property(timeoutProperty());
+ if (!timeoutScriptValue.isUndefined() && !timeoutScriptValue.isNull())
+ m_timeout = timeoutScriptValue.toInt32();
m_codeLocation = codeLocation;
m_predefinedProperties
@@ -123,7 +130,8 @@ void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const
<< highlightProperty()
<< ignoreDryRunProperty()
<< StringConstants::jobPoolProperty()
- << silentProperty();
+ << silentProperty()
+ << timeoutProperty();
}
QString AbstractCommand::fullDescription(const QString &productName) const
@@ -173,6 +181,8 @@ static QScriptValue js_CommandBase(QScriptContext *context, QScriptEngine *engin
engine->toScriptValue(AbstractCommand::defaultIgnoreDryRun()));
cmd.setProperty(silentProperty(),
engine->toScriptValue(AbstractCommand::defaultIsSilent()));
+ cmd.setProperty(timeoutProperty(),
+ engine->toScriptValue(AbstractCommand::defaultTimeout()));
return cmd;
}
diff --git a/src/lib/corelib/buildgraph/rulecommands.h b/src/lib/corelib/buildgraph/rulecommands.h
index d9d561454..d4d70d591 100644
--- a/src/lib/corelib/buildgraph/rulecommands.h
+++ b/src/lib/corelib/buildgraph/rulecommands.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -70,6 +71,7 @@ public:
static QString defaultHighLight() { return {}; }
static bool defaultIgnoreDryRun() { return false; }
static bool defaultIsSilent() { return false; }
+ static int defaultTimeout() { return -1; }
virtual CommandType type() const = 0;
virtual bool equals(const AbstractCommand *other) const;
@@ -83,6 +85,7 @@ public:
bool isSilent() const { return m_silent; }
QString jobPool() const { return m_jobPool; }
CodeLocation codeLocation() const { return m_codeLocation; }
+ int timeout() const { return m_timeout; }
const QVariantMap &properties() const { return m_properties; }
@@ -100,7 +103,7 @@ private:
{
pool.serializationOp<opType>(m_description, m_extendedDescription, m_highlight,
m_ignoreDryRun, m_silent, m_codeLocation, m_jobPool,
- m_properties);
+ m_timeout, m_properties);
}
QString m_description;
@@ -110,6 +113,7 @@ private:
bool m_silent;
CodeLocation m_codeLocation;
QString m_jobPool;
+ int m_timeout;
QVariantMap m_properties;
};
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index a9ca5131a..92d7eb052 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -198,7 +198,24 @@ QbsLibrary {
"generatableprojectiterator.h",
"generator.cpp",
"generatordata.cpp",
+ "generatorutils.cpp",
+ "generatorutils.h",
+ "generatorversioninfo.cpp",
+ "generatorversioninfo.h",
"igeneratableprojectvisitor.h",
+ "ixmlnodevisitor.h",
+ "xmlproject.cpp",
+ "xmlproject.h",
+ "xmlprojectwriter.cpp",
+ "xmlprojectwriter.h",
+ "xmlproperty.cpp",
+ "xmlproperty.h",
+ "xmlpropertygroup.cpp",
+ "xmlpropertygroup.h",
+ "xmlworkspace.cpp",
+ "xmlworkspace.h",
+ "xmlworkspacewriter.cpp",
+ "xmlworkspacewriter.h",
]
}
Group {
diff --git a/src/lib/corelib/generators/generators.pri b/src/lib/corelib/generators/generators.pri
index 093e45f40..e9730d895 100644
--- a/src/lib/corelib/generators/generators.pri
+++ b/src/lib/corelib/generators/generators.pri
@@ -3,13 +3,31 @@ include(../../../install_prefix.pri)
SOURCES += \
$$PWD/generatableprojectiterator.cpp \
$$PWD/generator.cpp \
- $$PWD/generatordata.cpp
+ $$PWD/generatordata.cpp \
+ $$PWD/generatorutils.cpp \
+ $$PWD/generatorversioninfo.cpp \
+ $$PWD/xmlproject.cpp \
+ $$PWD/xmlprojectwriter.cpp\
+ $$PWD/xmlproperty.cpp \
+ $$PWD/xmlpropertygroup.cpp \
+ $$PWD/xmlworkspace.cpp \
+ $$PWD/xmlworkspacewriter.cpp
HEADERS += \
$$PWD/generatableprojectiterator.h \
$$PWD/generator.h \
$$PWD/generatordata.h \
- $$PWD/igeneratableprojectvisitor.h
+ $$PWD/generatorutils.h \
+ $$PWD/generatorversioninfo.h \
+ $$PWD/igeneratableprojectvisitor.h \
+ $$PWD/ixmlnodevisitor.h \
+ $$PWD/ixmlnodevisitor.h \
+ $$PWD/xmlproject.h \
+ $$PWD/xmlprojectwriter.h \
+ $$PWD/xmlproperty.h \
+ $$PWD/xmlpropertygroup.h \
+ $$PWD/xmlworkspace.h \
+ $$PWD/xmlworkspacewriter.h
!qbs_no_dev_install {
generators_headers.files = \
diff --git a/src/lib/corelib/generators/generatorutils.cpp b/src/lib/corelib/generators/generatorutils.cpp
new file mode 100644
index 000000000..872adbba2
--- /dev/null
+++ b/src/lib/corelib/generators/generatorutils.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "generatorutils.h"
+
+namespace qbs {
+namespace gen {
+namespace utils {
+
+QString architectureName(Architecture arch)
+{
+ switch (arch) {
+ case Architecture::Arm:
+ return QStringLiteral("arm");
+ case Architecture::Avr:
+ return QStringLiteral("avr");
+ case Architecture::Mcs51:
+ return QStringLiteral("mcs51");
+ default:
+ return QStringLiteral("unknown");
+ }
+}
+
+Architecture architecture(const Project &qbsProject)
+{
+ const auto qbsArch = qbsProject.projectConfiguration()
+ .value(Internal::StringConstants::qbsModule()).toMap()
+ .value(QStringLiteral("architecture")).toString();
+
+ if (qbsArch == QLatin1String("arm"))
+ return Architecture::Arm;
+ if (qbsArch == QLatin1String("avr"))
+ return Architecture::Avr;
+ if (qbsArch == QLatin1String("mcs51"))
+ return Architecture::Mcs51;
+ if (qbsArch == QLatin1String("stm8"))
+ return Architecture::Stm8;
+ return Architecture::Unknown;
+}
+
+QString buildConfigurationName(const Project &qbsProject)
+{
+ return qbsProject.projectConfiguration()
+ .value(Internal::StringConstants::qbsModule()).toMap()
+ .value(QStringLiteral("configurationName")).toString();
+}
+
+int debugInformation(const ProductData &qbsProduct)
+{
+ return qbsProduct.moduleProperties().getModuleProperty(
+ Internal::StringConstants::qbsModule(),
+ QStringLiteral("debugInformation"))
+ .toInt();
+}
+
+QString buildRootPath(const Project &qbsProject)
+{
+ QDir dir(qbsProject.projectData().buildDirectory());
+ dir.cdUp();
+ return dir.absolutePath();
+}
+
+QString relativeFilePath(const QString &baseDirectory,
+ const QString &fullFilePath)
+{
+ return QDir(baseDirectory).relativeFilePath(fullFilePath);
+}
+
+QString binaryOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ return QDir(baseDirectory).relativeFilePath(
+ qbsProduct.buildDirectory())
+ + QLatin1String("/bin");
+}
+
+QString objectsOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ return QDir(baseDirectory).relativeFilePath(
+ qbsProduct.buildDirectory())
+ + QLatin1String("/obj");
+}
+
+QString listingOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ return QDir(baseDirectory).relativeFilePath(
+ qbsProduct.buildDirectory())
+ + QLatin1String("/lst");
+}
+
+std::vector<ProductData> dependenciesOf(const ProductData &qbsProduct,
+ const GeneratableProject &genProject,
+ const QString &configurationName)
+{
+ std::vector<ProductData> result;
+ const auto depsNames = qbsProduct.dependencies();
+ for (const auto &product : qAsConst(genProject.products)) {
+ const auto pt = product.type();
+ if (!pt.contains(QLatin1String("staticlibrary")))
+ continue;
+ const auto pn = product.name();
+ if (!depsNames.contains(pn))
+ continue;
+ result.push_back(product.data.value(configurationName));
+ }
+ return result;
+}
+
+QString targetBinary(const ProductData &qbsProduct)
+{
+ const auto type = qbsProduct.type();
+ if (type.contains(QLatin1String("application"))) {
+ return QFileInfo(qbsProduct.targetExecutable()).fileName();
+ } else if (type.contains(QLatin1String("staticlibrary"))) {
+ const auto artifacts = qbsProduct.targetArtifacts();
+ for (const auto &artifact : artifacts) {
+ if (artifact.fileTags().contains(QLatin1String("staticlibrary")))
+ return QFileInfo(artifact.filePath()).fileName();
+ }
+ }
+
+ return {};
+}
+
+QString targetBinaryPath(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ return binaryOutputDirectory(baseDirectory, qbsProduct)
+ + QLatin1Char('/') + targetBinary(qbsProduct);
+}
+
+QString cppStringModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName)
+{
+ return qbsProps.getModuleProperty(
+ Internal::StringConstants::cppModule(),
+ propertyName).toString().trimmed();
+}
+
+bool cppBooleanModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName)
+{
+ return qbsProps.getModuleProperty(
+ Internal::StringConstants::cppModule(),
+ propertyName).toBool();
+}
+
+int cppIntegerModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName)
+{
+ return qbsProps.getModuleProperty(
+ Internal::StringConstants::cppModule(),
+ propertyName).toInt();
+}
+
+QStringList cppStringModuleProperties(const PropertyMap &qbsProps,
+ const QStringList &propertyNames)
+{
+ QStringList properties;
+ for (const auto &propertyName : propertyNames) {
+ const auto entries = qbsProps.getModuleProperty(
+ Internal::StringConstants::cppModule(),
+ propertyName).toStringList();
+ for (const auto &entry : entries)
+ properties.push_back(entry.trimmed());
+ }
+ return properties;
+}
+
+QVariantList cppVariantModuleProperties(const PropertyMap &qbsProps,
+ const QStringList &propertyNames)
+{
+ QVariantList properties;
+ for (const auto &propertyName : propertyNames) {
+ properties << qbsProps.getModuleProperty(
+ Internal::StringConstants::cppModule(),
+ propertyName).toList();
+ }
+ return properties;
+}
+
+} // namespace utils
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/generatorutils.h b/src/lib/corelib/generators/generatorutils.h
new file mode 100644
index 000000000..885315e4d
--- /dev/null
+++ b/src/lib/corelib/generators/generatorutils.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_UTILS_H
+#define GENERATORS_UTILS_H
+
+#include <qbs.h>
+
+#include <tools/qbs_export.h>
+#include <tools/stringconstants.h>
+
+namespace qbs {
+namespace gen {
+namespace utils {
+
+enum class Architecture {
+ Arm,
+ Avr,
+ Mcs51,
+ Stm8,
+ Unknown
+};
+
+QBS_EXPORT QString architectureName(Architecture arch);
+QBS_EXPORT Architecture architecture(const Project &qbsProject);
+QBS_EXPORT QString buildConfigurationName(const Project &qbsProject);
+QBS_EXPORT int debugInformation(const ProductData &qbsProduct);
+QBS_EXPORT QString buildRootPath(const Project &qbsProject);
+QBS_EXPORT QString relativeFilePath(const QString &baseDirectory,
+ const QString &fullFilePath);
+QBS_EXPORT QString binaryOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+QBS_EXPORT QString objectsOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+QBS_EXPORT QString listingOutputDirectory(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+QBS_EXPORT std::vector<ProductData> dependenciesOf(const ProductData &qbsProduct,
+ const GeneratableProject &genProject,
+ const QString &configurationName);
+QBS_EXPORT QString targetBinary(const ProductData &qbsProduct);
+QBS_EXPORT QString targetBinaryPath(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+QBS_EXPORT QString cppStringModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName);
+QBS_EXPORT bool cppBooleanModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName);
+QBS_EXPORT int cppIntegerModuleProperty(const PropertyMap &qbsProps,
+ const QString &propertyName);
+QBS_EXPORT QStringList cppStringModuleProperties(const PropertyMap &qbsProps,
+ const QStringList &propertyNames);
+QBS_EXPORT QVariantList cppVariantModuleProperties(const PropertyMap &qbsProps,
+ const QStringList &propertyNames);
+
+template <typename T>
+bool inBounds(const T &value, const T &low, const T &high)
+{
+ return !(value < low) && !(high < value);
+}
+
+} // namespace utils
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_UTILS_H
diff --git a/src/lib/corelib/generators/generatorversioninfo.cpp b/src/lib/corelib/generators/generatorversioninfo.cpp
new file mode 100644
index 000000000..3e2106b57
--- /dev/null
+++ b/src/lib/corelib/generators/generatorversioninfo.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "generatorversioninfo.h"
+
+namespace qbs {
+namespace gen {
+
+VersionInfo::VersionInfo(const Version &version,
+ const std::set<utils::Architecture> &archs)
+ : m_version(version), m_archs(archs)
+{
+}
+
+bool VersionInfo::operator<(const VersionInfo &other) const
+{
+ return m_version < other.m_version;
+}
+
+bool VersionInfo::operator==(const VersionInfo &other) const
+{
+ return m_version == other.m_version
+ && m_archs == other.m_archs;
+}
+
+Version VersionInfo::version() const
+{
+ return m_version;
+}
+
+bool VersionInfo::containsArchitecture(utils::Architecture arch) const
+{
+ return m_archs.find(arch) != m_archs.cend();
+}
+
+int VersionInfo::marketingVersion() const
+{
+ return m_version.majorVersion();
+}
+
+quint32 qHash(const VersionInfo &info)
+{
+ return qHash(info.version().toString());
+}
+
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/generatorversioninfo.h b/src/lib/corelib/generators/generatorversioninfo.h
new file mode 100644
index 000000000..65bfcf685
--- /dev/null
+++ b/src/lib/corelib/generators/generatorversioninfo.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GENERATORS_VERSION_INFO_H
+#define GENERATORS_VERSION_INFO_H
+
+#include "generatorutils.h"
+
+#include <tools/qbs_export.h>
+#include <tools/version.h>
+
+#include <set>
+
+namespace qbs {
+namespace gen {
+
+class QBS_EXPORT VersionInfo
+{
+public:
+ VersionInfo(const Version &version,
+ const std::set<utils::Architecture> &archs);
+ virtual ~VersionInfo() = default;
+
+ bool operator<(const VersionInfo &other) const;
+ bool operator==(const VersionInfo &other) const;
+
+ Version version() const;
+ bool containsArchitecture(utils::Architecture arch) const;
+
+ virtual int marketingVersion() const;
+
+private:
+ Version m_version;
+ std::set<utils::Architecture> m_archs;
+};
+
+quint32 qHash(const VersionInfo &info);
+
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_VERSION_INFO_H
diff --git a/src/lib/corelib/generators/ixmlnodevisitor.h b/src/lib/corelib/generators/ixmlnodevisitor.h
new file mode 100644
index 000000000..6d62c86ed
--- /dev/null
+++ b/src/lib/corelib/generators/ixmlnodevisitor.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_INODE_VISITOR_H
+#define GENERATORS_XML_INODE_VISITOR_H
+
+#include <tools/qbs_export.h>
+
+#include <QtCore/qxmlstream.h>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class Project;
+class Property;
+class PropertyGroup;
+class Workspace;
+
+class QBS_EXPORT INodeVisitor
+{
+public:
+ virtual ~INodeVisitor() {}
+
+ virtual void visitStart(const Workspace *workspace) { Q_UNUSED(workspace) }
+ virtual void visitEnd(const Workspace *workspace) { Q_UNUSED(workspace) }
+
+ virtual void visitStart(const Project *project) { Q_UNUSED(project) }
+ virtual void visitEnd(const Project *project) { Q_UNUSED(project) }
+
+ virtual void visitStart(const Property *property) = 0;
+ virtual void visitEnd(const Property *property) = 0;
+
+ virtual void visitStart(const PropertyGroup *propertyGroup) = 0;
+ virtual void visitEnd(const PropertyGroup *propertyGroup) = 0;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_INODE_VISITOR_H
diff --git a/src/lib/corelib/generators/xmlproject.cpp b/src/lib/corelib/generators/xmlproject.cpp
new file mode 100644
index 000000000..becd31dda
--- /dev/null
+++ b/src/lib/corelib/generators/xmlproject.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xmlproject.h"
+#include "ixmlnodevisitor.h"
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+void Project::accept(INodeVisitor *visitor) const
+{
+ visitor->visitStart(this);
+
+ for (const auto &child : children())
+ child->accept(visitor);
+
+ visitor->visitEnd(this);
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlproject.h b/src/lib/corelib/generators/xmlproject.h
new file mode 100644
index 000000000..a7f5b2b65
--- /dev/null
+++ b/src/lib/corelib/generators/xmlproject.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_PROJECT_H
+#define GENERATORS_XML_PROJECT_H
+
+#include "xmlproperty.h"
+
+#include <tools/qbs_export.h>
+
+#include <memory>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class QBS_EXPORT Project : public Property
+{
+public:
+ void accept(INodeVisitor *visitor) const final;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_PROJECT_H
diff --git a/src/lib/corelib/generators/xmlprojectwriter.cpp b/src/lib/corelib/generators/xmlprojectwriter.cpp
new file mode 100644
index 000000000..5b96564bd
--- /dev/null
+++ b/src/lib/corelib/generators/xmlprojectwriter.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xmlproject.h"
+#include "xmlprojectwriter.h"
+#include "xmlproperty.h"
+#include "xmlpropertygroup.h"
+
+#include <ostream>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+ProjectWriter::ProjectWriter(std::ostream *device)
+ : m_device(device)
+{
+ m_writer.reset(new QXmlStreamWriter(&m_buffer));
+ m_writer->setAutoFormatting(true);
+}
+
+bool ProjectWriter::write(const Project *project)
+{
+ m_buffer.clear();
+ m_writer->writeStartDocument();
+ project->accept(this);
+ m_writer->writeEndDocument();
+ if (m_writer->hasError())
+ return false;
+ m_device->write(&*std::begin(m_buffer), m_buffer.size());
+ return m_device->good();
+}
+
+void ProjectWriter::visitStart(const Property *property)
+{
+ const auto value = property->value().toString();
+ const auto name = QString::fromUtf8(property->name());
+ m_writer->writeTextElement(name, value);
+}
+
+void ProjectWriter::visitEnd(const Property *property)
+{
+ Q_UNUSED(property)
+}
+
+void ProjectWriter::visitStart(const PropertyGroup *propertyGroup)
+{
+ const auto name = QString::fromUtf8(propertyGroup->name());
+ m_writer->writeStartElement(name);
+}
+
+void ProjectWriter::visitEnd(const PropertyGroup *propertyGroup)
+{
+ Q_UNUSED(propertyGroup)
+ m_writer->writeEndElement();
+}
+
+QXmlStreamWriter *ProjectWriter::writer() const
+{
+ return m_writer.get();
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlprojectwriter.h b/src/lib/corelib/generators/xmlprojectwriter.h
new file mode 100644
index 000000000..da4100a92
--- /dev/null
+++ b/src/lib/corelib/generators/xmlprojectwriter.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_PROJECT_WRITER_H
+#define GENERATORS_XML_PROJECT_WRITER_H
+
+#include "ixmlnodevisitor.h"
+
+#include <tools/qbs_export.h>
+
+#include <memory>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class QBS_EXPORT ProjectWriter : public INodeVisitor
+{
+ Q_DISABLE_COPY(ProjectWriter)
+public:
+ explicit ProjectWriter(std::ostream *device);
+ bool write(const Project *project);
+
+protected:
+ QXmlStreamWriter *writer() const;
+
+private:
+ void visitStart(const Property *property) final;
+ void visitEnd(const Property *property) final;
+
+ void visitStart(const PropertyGroup *propertyGroup) final;
+ void visitEnd(const PropertyGroup *propertyGroup) final;
+
+ std::ostream *m_device = nullptr;
+ QByteArray m_buffer;
+ std::unique_ptr<QXmlStreamWriter> m_writer;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_PROJECT_WRITER_H
diff --git a/src/lib/corelib/generators/xmlproperty.cpp b/src/lib/corelib/generators/xmlproperty.cpp
new file mode 100644
index 000000000..ae41eab4a
--- /dev/null
+++ b/src/lib/corelib/generators/xmlproperty.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "ixmlnodevisitor.h"
+#include "xmlproperty.h"
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+Property::Property(QByteArray name, QVariant value)
+{
+ setName(std::move(name));
+ setValue(std::move(value));
+}
+
+void Property::accept(INodeVisitor *visitor) const
+{
+ visitor->visitStart(this);
+
+ for (const auto &child : children())
+ child->accept(visitor);
+
+ visitor->visitEnd(this);
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlproperty.h b/src/lib/corelib/generators/xmlproperty.h
new file mode 100644
index 000000000..795735881
--- /dev/null
+++ b/src/lib/corelib/generators/xmlproperty.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_PROPERTY_H
+#define GENERATORS_XML_PROPERTY_H
+
+#include <tools/qbs_export.h>
+
+#include <QtCore/qvariant.h>
+
+#include <memory>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class INodeVisitor;
+
+class QBS_EXPORT Property
+{
+ Q_DISABLE_COPY(Property)
+public:
+ Property() = default;
+ explicit Property(QByteArray name, QVariant value);
+ virtual ~Property() = default;
+
+ QByteArray name() const { return m_name; }
+ void setName(QByteArray name) { m_name = std::move(name); }
+
+ QVariant value() const { return m_value; }
+ void setValue(QVariant value) { m_value = std::move(value); }
+
+ template<class T>
+ T *appendChild(std::unique_ptr<T> child) {
+ const auto p = child.get();
+ m_children.push_back(std::move(child));
+ return p;
+ }
+
+ template<class T, class... Args>
+ T *appendChild(Args&&... args) {
+ return appendChild(std::make_unique<T>(std::forward<Args>(args)...));
+ }
+
+ virtual void accept(INodeVisitor *visitor) const;
+
+protected:
+ const std::vector<std::unique_ptr<Property>> &children() const
+ { return m_children; }
+
+private:
+ QByteArray m_name;
+ QVariant m_value;
+ std::vector<std::unique_ptr<Property>> m_children;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_PROPERTY_H
diff --git a/src/lib/corelib/generators/xmlpropertygroup.cpp b/src/lib/corelib/generators/xmlpropertygroup.cpp
new file mode 100644
index 000000000..2111b9b1e
--- /dev/null
+++ b/src/lib/corelib/generators/xmlpropertygroup.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "ixmlnodevisitor.h"
+#include "xmlpropertygroup.h"
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+PropertyGroup::PropertyGroup(QByteArray name)
+{
+ setName(std::move(name));
+}
+
+void PropertyGroup::appendProperty(QByteArray name, QVariant value)
+{
+ appendChild<Property>(std::move(name), std::move(value));
+}
+
+void PropertyGroup::appendMultiLineProperty(
+ QByteArray key, QStringList values, QChar sep)
+{
+ const auto line = values.join(std::move(sep));
+ appendProperty(std::move(key), QVariant::fromValue(line));
+}
+
+void PropertyGroup::accept(INodeVisitor *visitor) const
+{
+ visitor->visitStart(this);
+
+ for (const auto &child : children())
+ child->accept(visitor);
+
+ visitor->visitEnd(this);
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlpropertygroup.h b/src/lib/corelib/generators/xmlpropertygroup.h
new file mode 100644
index 000000000..e63b515fc
--- /dev/null
+++ b/src/lib/corelib/generators/xmlpropertygroup.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_PROPERTY_GROUP_H
+#define GENERATORS_XML_PROPERTY_GROUP_H
+
+#include "generatorversioninfo.h"
+#include "xmlproperty.h"
+
+#include <tools/qbs_export.h>
+
+#include <memory>
+
+namespace qbs {
+
+class ProductData;
+class Project;
+
+namespace gen {
+namespace xml {
+
+class QBS_EXPORT PropertyGroup : public Property
+{
+public:
+ explicit PropertyGroup(QByteArray name);
+
+ void appendProperty(QByteArray name, QVariant value);
+ void appendMultiLineProperty(QByteArray key, QStringList values,
+ QChar sep = QLatin1Char(','));
+
+ void accept(INodeVisitor *visitor) const final;
+};
+
+class PropertyGroupFactory
+{
+public:
+ virtual ~PropertyGroupFactory() = default;
+ virtual bool canCreate(utils::Architecture arch,
+ const Version &version) const = 0;
+
+ virtual std::unique_ptr<PropertyGroup> create(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const = 0;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_PROPERTY_GROUP_H
diff --git a/src/lib/corelib/generators/xmlworkspace.cpp b/src/lib/corelib/generators/xmlworkspace.cpp
new file mode 100644
index 000000000..8913ceffd
--- /dev/null
+++ b/src/lib/corelib/generators/xmlworkspace.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ixmlnodevisitor.h"
+#include "xmlproperty.h"
+#include "xmlpropertygroup.h"
+#include "xmlworkspace.h"
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+Workspace::Workspace(const QString &workspacePath)
+ : m_baseDirectory(QFileInfo(workspacePath).absoluteDir())
+{
+}
+
+void Workspace::accept(INodeVisitor *visitor) const
+{
+ visitor->visitStart(this);
+
+ for (const auto &child : children())
+ child->accept(visitor);
+
+ visitor->visitEnd(this);
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlworkspace.h b/src/lib/corelib/generators/xmlworkspace.h
new file mode 100644
index 000000000..beab22c4a
--- /dev/null
+++ b/src/lib/corelib/generators/xmlworkspace.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_WWORKSPACE_H
+#define GENERATORS_XML_WWORKSPACE_H
+
+#include "xmlproperty.h"
+
+#include <tools/qbs_export.h>
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class QBS_EXPORT Workspace : public Property
+{
+public:
+ explicit Workspace(const QString &workspacePath);
+ void accept(INodeVisitor *visitor) const final;
+
+ virtual void addProject(const QString &projectPath) = 0;
+
+protected:
+ const QDir m_baseDirectory;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_WWORKSPACE_H
diff --git a/src/lib/corelib/generators/xmlworkspacewriter.cpp b/src/lib/corelib/generators/xmlworkspacewriter.cpp
new file mode 100644
index 000000000..2358d4047
--- /dev/null
+++ b/src/lib/corelib/generators/xmlworkspacewriter.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "xmlproperty.h"
+#include "xmlpropertygroup.h"
+#include "xmlworkspace.h"
+#include "xmlworkspacewriter.h"
+
+#include <ostream>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+WorkspaceWriter::WorkspaceWriter(std::ostream *device)
+ : m_device(device)
+{
+ m_writer.reset(new QXmlStreamWriter(&m_buffer));
+ m_writer->setAutoFormatting(true);
+}
+
+bool WorkspaceWriter::write(const Workspace *workspace)
+{
+ m_buffer.clear();
+ m_writer->writeStartDocument();
+ workspace->accept(this);
+ m_writer->writeEndDocument();
+ if (m_writer->hasError())
+ return false;
+ m_device->write(&*std::begin(m_buffer), m_buffer.size());
+ return m_device->good();
+}
+
+void WorkspaceWriter::visitStart(const Property *property)
+{
+ const auto value = property->value().toString();
+ const auto name = QString::fromUtf8(property->name());
+ m_writer->writeTextElement(name, value);
+}
+
+void WorkspaceWriter::visitEnd(const Property *property)
+{
+ Q_UNUSED(property)
+}
+
+void WorkspaceWriter::visitStart(const PropertyGroup *propertyGroup)
+{
+ const auto name = QString::fromUtf8(propertyGroup->name());
+ m_writer->writeStartElement(name);
+}
+
+void WorkspaceWriter::visitEnd(const PropertyGroup *propertyGroup)
+{
+ Q_UNUSED(propertyGroup)
+ m_writer->writeEndElement();
+}
+
+QXmlStreamWriter *WorkspaceWriter::writer() const
+{
+ return m_writer.get();
+}
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
diff --git a/src/lib/corelib/generators/xmlworkspacewriter.h b/src/lib/corelib/generators/xmlworkspacewriter.h
new file mode 100644
index 000000000..73e7d0686
--- /dev/null
+++ b/src/lib/corelib/generators/xmlworkspacewriter.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef GENERATORS_XML_WORKSPACE_WRITER_H
+#define GENERATORS_XML_WORKSPACE_WRITER_H
+
+#include "ixmlnodevisitor.h"
+
+#include <tools/qbs_export.h>
+
+#include <memory>
+
+namespace qbs {
+namespace gen {
+namespace xml {
+
+class QBS_EXPORT WorkspaceWriter : public INodeVisitor
+{
+ Q_DISABLE_COPY(WorkspaceWriter)
+public:
+ explicit WorkspaceWriter(std::ostream *device);
+ bool write(const Workspace *workspace);
+
+protected:
+ QXmlStreamWriter *writer() const;
+
+private:
+ void visitStart(const Property *property) final;
+ void visitEnd(const Property *property) final;
+
+ void visitStart(const PropertyGroup *propertyGroup) final;
+ void visitEnd(const PropertyGroup *propertyGroup) final;
+
+ std::ostream *m_device = nullptr;
+ QByteArray m_buffer;
+ std::unique_ptr<QXmlStreamWriter> m_writer;
+};
+
+} // namespace xml
+} // namespace gen
+} // namespace qbs
+
+#endif // GENERATORS_XML_WORKSPACE_WRITER_H
diff --git a/src/lib/corelib/tools/version.cpp b/src/lib/corelib/tools/version.cpp
index d2b337d3a..dfb7f49b7 100644
--- a/src/lib/corelib/tools/version.cpp
+++ b/src/lib/corelib/tools/version.cpp
@@ -105,13 +105,17 @@ Version Version::fromString(const QString &versionString, bool buildNumberAllowe
return Version{majorNr, minorNr, patchNr, buildNr};
}
-QString Version::toString() const
+QString Version::toString(const QChar &separator, const QChar &buildSeparator) const
{
if (m_build) {
- return QString(QStringLiteral("%1.%2.%3-%4"))
- .arg(m_major).arg(m_minor).arg(m_patch).arg(m_build);
+ return QStringLiteral("%1%5%2%5%3%6%4")
+ .arg(QString::number(m_major), QString::number(m_minor),
+ QString::number(m_patch), QString::number(m_build),
+ separator, buildSeparator);
}
- return QString(QStringLiteral("%1.%2.%3")).arg(m_major).arg(m_minor).arg(m_patch);
+ return QStringLiteral("%1%4%2%4%3")
+ .arg(QString::number(m_major), QString::number(m_minor),
+ QString::number(m_patch), separator);
}
int compare(const Version &lhs, const Version &rhs)
diff --git a/src/lib/corelib/tools/version.h b/src/lib/corelib/tools/version.h
index 4f5e46500..a0239a6e4 100644
--- a/src/lib/corelib/tools/version.h
+++ b/src/lib/corelib/tools/version.h
@@ -42,6 +42,7 @@
#include "qbs_export.h"
+#include <QtCore/qchar.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
@@ -71,7 +72,8 @@ public:
void setBuildNumber(int nr);
static Version fromString(const QString &versionString, bool buildNumberAllowed = false);
- QString toString() const;
+ QString toString(const QChar &separator = QLatin1Char('.'),
+ const QChar &buildSeparator = QLatin1Char('-')) const;
private:
int m_major;
diff --git a/src/plugins/generator/generator.pro b/src/plugins/generator/generator.pro
index 1607aa14d..4a3861321 100644
--- a/src/plugins/generator/generator.pro
+++ b/src/plugins/generator/generator.pro
@@ -1,2 +1,6 @@
TEMPLATE = subdirs
-SUBDIRS = clangcompilationdb makefilegenerator visualstudio
+SUBDIRS += clangcompilationdb
+SUBDIRS += makefilegenerator
+SUBDIRS += visualstudio
+SUBDIRS += iarew
+SUBDIRS += keiluv
diff --git a/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp
new file mode 100644
index 000000000..210c757da
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armarchiversettingsgroup_v8.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+constexpr int kArchiverArchiveVersion = 0;
+constexpr int kArchiverDataVersion = 0;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ outputFile = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory, qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+} // namespace
+
+// ArmArchiverSettingsGroup
+
+ArmArchiverSettingsGroup::ArmArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("IARCHIVE"));
+ setArchiveVersion(kArchiverArchiveVersion);
+ setDataVersion(kArchiverDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void ArmArchiverSettingsGroup::buildOutputPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'IarchiveOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("IarchiveOverride"),
+ {}, {1});
+ // Add 'IarchiveOutput' item (Output filename).
+ addOptionsGroup(QByteArrayLiteral("IarchiveOutput"),
+ {}, {opts.outputFile});
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h
new file mode 100644
index 000000000..c99c2eeba
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H
+#define QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmArchiverSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit ArmArchiverSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp
new file mode 100644
index 000000000..b7870d626
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armassemblersettingsgroup_v8.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+constexpr int kAssemblerArchiveVersion = 2;
+constexpr int kAssemblerDataVersion = 10;
+
+namespace {
+
+// Language page options.
+
+struct LanguagePageOptions final
+{
+ enum MacroQuoteCharacter {
+ AngleBracketsQuote,
+ RoundBracketsQuote,
+ SquareBracketsQuote,
+ FigureBracketsQuote
+ };
+
+ explicit LanguagePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleAssemblerFlags(qbsProps);
+ enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+"));
+ allowAlternativeRegister = flags.contains(QLatin1String("-j"));
+ disableCodeMemoryDataReads = flags.contains(
+ QLatin1String("--no_literal_pool"));
+ if (flags.contains(QLatin1String("-M<>")))
+ macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote;
+ else if (flags.contains(QLatin1String("-M()")))
+ macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote;
+ else if (flags.contains(QLatin1String("-M[]")))
+ macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote;
+ else if (flags.contains(QLatin1String("-M{}")))
+ macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote;
+ }
+
+ MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote;
+ int enableSymbolsCaseSensitive = 0;
+ int allowAlternativeRegister = 0;
+ int disableCodeMemoryDataReads = 0;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const QString &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString warningLevel = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ if (warningLevel == QLatin1String("all")) {
+ enableWarnings = 0;
+ enableAllWarnings = 0;
+ } else if (warningLevel == QLatin1String("none")) {
+ enableWarnings = 1;
+ enableAllWarnings = 0;
+ } else {
+ enableWarnings = 0;
+ enableAllWarnings = 1;
+ }
+ }
+
+ int enableWarnings = 0;
+ int enableAllWarnings = 0;
+};
+
+} // namespace
+
+// ArmAssemblerSettingsGroup
+
+ArmAssemblerSettingsGroup::ArmAssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("AARM"));
+ setArchiveVersion(kAssemblerArchiveVersion);
+ setDataVersion(kAssemblerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildLanguagePage(qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void ArmAssemblerSettingsGroup::buildLanguagePage(
+ const ProductData &qbsProduct)
+{
+ const LanguagePageOptions opts(qbsProduct);
+ // Add 'ACaseSensitivity' item (User symbols are case sensitive).
+ addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"),
+ {}, {opts.enableSymbolsCaseSensitive});
+ // Add 'AltRegisterNames' item (Allow alternative register names,
+ // mnemonics and operands).
+ addOptionsGroup(QByteArrayLiteral("AltRegisterNames"),
+ {}, {opts.allowAlternativeRegister});
+ // Add 'AsmNoLiteralPool' item (No data reads in code memory).
+ addOptionsGroup(QByteArrayLiteral("AsmNoLiteralPool"),
+ {}, {opts.disableCodeMemoryDataReads});
+ // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>).
+ addOptionsGroup(QByteArrayLiteral("MacroChars"),
+ {0}, {opts.macroQuoteCharacter});
+}
+void ArmAssemblerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'ADebug' item (Generate debug information).
+ addOptionsGroup(QByteArrayLiteral("ADebug"),
+ {}, {opts.debugInfo});
+}
+
+void ArmAssemblerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'ADefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("ADefines"),
+ {}, opts.defineSymbols);
+ // Add 'AUserIncludes' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("AUserIncludes"),
+ {}, opts.includePaths);
+}
+
+void ArmAssemblerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'AWarnEnable' item (Enable/disable warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnEnable"),
+ {}, {opts.enableWarnings});
+ // Add 'AWarnWhat' item (Enable/disable all warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnWhat"),
+ {}, {opts.enableAllWarnings});
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h
new file mode 100644
index 000000000..620dcf1f5
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H
+#define QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmAssemblerSettingsGroup final
+ : public IarewSettingsPropertyGroup
+{
+public:
+ explicit ArmAssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildLanguagePage(const ProductData &qbsProduct);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp
new file mode 100644
index 000000000..a16e57a42
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armarchiversettingsgroup_v8.h"
+#include "armassemblersettingsgroup_v8.h"
+#include "armbuildconfigurationgroup_v8.h"
+#include "armcompilersettingsgroup_v8.h"
+#include "armgeneralsettingsgroup_v8.h"
+#include "armlinkersettingsgroup_v8.h"
+
+#include "../../iarewtoolchainpropertygroup.h"
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+ArmBuildConfigurationGroup::ArmBuildConfigurationGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup("configuration")
+{
+ // Append configuration name item.
+ const QString cfgName = gen::utils::buildConfigurationName(qbsProject);
+ appendProperty("name", cfgName);
+
+ // Apend toolchain name group item.
+ appendChild<IarewToolchainPropertyGroup>("ARM");
+
+ // Append debug info item.
+ const int debugBuild = gen::utils::debugInformation(qbsProduct);
+ appendProperty("debug", debugBuild);
+
+ // Append settings group items.
+ appendChild<ArmArchiverSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<ArmAssemblerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<ArmCompilerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<ArmGeneralSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<ArmLinkerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+}
+
+bool ArmBuildConfigurationGroupFactory::canCreate(
+ gen::utils::Architecture arch,
+ const Version &version) const
+{
+ return arch == gen::utils::Architecture::Arm
+ && version.majorVersion() == 8;
+}
+
+std::unique_ptr<gen::xml::PropertyGroup>
+ArmBuildConfigurationGroupFactory::create(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const
+{
+ const auto group = new ArmBuildConfigurationGroup(
+ qbsProject, qbsProduct, qbsProductDeps);
+ return std::unique_ptr<ArmBuildConfigurationGroup>(group);
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h
new file mode 100644
index 000000000..26370c9b8
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H
+#define QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmBuildConfigurationGroup final
+ : public gen::xml::PropertyGroup
+{
+private:
+ explicit ArmBuildConfigurationGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+ friend class ArmBuildConfigurationGroupFactory;
+};
+
+class ArmBuildConfigurationGroupFactory final
+ : public gen::xml::PropertyGroupFactory
+{
+public:
+ bool canCreate(gen::utils::Architecture arch,
+ const Version &version) const final;
+
+ std::unique_ptr<gen::xml::PropertyGroup> create(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const final;
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp
new file mode 100644
index 000000000..bbe5b1758
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp
@@ -0,0 +1,478 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armcompilersettingsgroup_v8.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+constexpr int kCompilerArchiveVersion = 2;
+constexpr int kCompilerDataVersion = 34;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Language 1 page options.
+
+struct LanguageOnePageOptions final
+{
+ enum LanguageExtension {
+ CLanguageExtension,
+ CxxLanguageExtension,
+ AutoLanguageExtension
+ };
+
+ enum CLanguageDialect {
+ C89LanguageDialect,
+ C11LanguageDialect
+ };
+
+ enum LanguageConformance {
+ AllowIarExtension,
+ RelaxedStandard,
+ StrictStandard
+ };
+
+ explicit LanguageOnePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ // File extension based by default.
+ languageExtension = LanguageOnePageOptions::AutoLanguageExtension;
+ // Language dialect.
+ const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("cLanguageVersion")});
+ cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89"))
+ ? LanguageOnePageOptions::C89LanguageDialect
+ : LanguageOnePageOptions::C11LanguageDialect;
+
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ // Language conformance.
+ if (flags.contains(QLatin1String("-e")))
+ languageConformance = LanguageOnePageOptions::AllowIarExtension;
+ else if (flags.contains(QLatin1String("--strict")))
+ languageConformance = LanguageOnePageOptions::StrictStandard;
+ else
+ languageConformance = LanguageOnePageOptions::RelaxedStandard;
+ // Exceptions, rtti, static desrtuction.
+ enableExceptions = !flags.contains(QLatin1String("--no_exceptions"));
+ enableRtti = !flags.contains(QLatin1String("--no_rtti"));
+ destroyStaticObjects = !flags.contains(
+ QLatin1String("--no_static_destruction"));
+ allowVla = flags.contains(QLatin1String("--vla"));
+ enableInlineSemantics = flags.contains(QLatin1String("--use_c++_inline"));
+ requirePrototypes = flags.contains(QLatin1String("--require_prototypes"));
+ }
+
+ LanguageExtension languageExtension = AutoLanguageExtension;
+ CLanguageDialect cLanguageDialect = C89LanguageDialect;
+ LanguageConformance languageConformance = AllowIarExtension;
+ // C++ options.
+ int enableExceptions = 0;
+ int enableRtti = 0;
+ int destroyStaticObjects = 0;
+ int allowVla = 0;
+ int enableInlineSemantics = 0;
+ int requirePrototypes = 0;
+};
+
+// Language 2 page options.
+
+struct LanguageTwoPageOptions final
+{
+ enum PlainCharacter {
+ SignedCharacter,
+ UnsignedCharacter
+ };
+
+ enum FloatingPointSemantic {
+ StrictSemantic,
+ RelaxedSemantic
+ };
+
+ explicit LanguageTwoPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ plainCharacter = flags.contains(QLatin1String("--char_is_signed"))
+ ? LanguageTwoPageOptions::SignedCharacter
+ : LanguageTwoPageOptions::UnsignedCharacter;
+ floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp"))
+ ? LanguageTwoPageOptions::RelaxedSemantic
+ : LanguageTwoPageOptions::StrictSemantic;
+ }
+
+ PlainCharacter plainCharacter = SignedCharacter;
+ FloatingPointSemantic floatingPointSemantic = StrictSemantic;
+};
+
+// Optimizations page options.
+
+struct OptimizationsPageOptions final
+{
+ // Optimizations level radio-buttons with
+ // combo-box on "level" widget.
+
+ enum Strategy {
+ StrategyBalanced,
+ StrategySize,
+ StrategySpeed
+ };
+
+ enum Level {
+ LevelNone,
+ LevelLow,
+ LevelMedium,
+ LevelHigh
+ };
+
+ enum LevelSlave {
+ LevelSlave0,
+ LevelSlave1,
+ LevelSlave2,
+ LevelSlave3
+ };
+
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString optimization = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("optimization"));
+ if (optimization == QLatin1String("none")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategyBalanced;
+ optimizationLevel = OptimizationsPageOptions::LevelNone;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0;
+ } else if (optimization == QLatin1String("fast")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySpeed;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ } else if (optimization == QLatin1String("small")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySize;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ }
+
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ enableCommonSubexpressionElimination = !flags.contains(
+ QLatin1String("--no_cse"));
+ enableLoopUnroll = !flags.contains(
+ QLatin1String("--no_unroll"));
+ enableFunctionInlining = !flags.contains(
+ QLatin1String("--no_inline"));
+ enableCodeMotion = !flags.contains(
+ QLatin1String("--no_code_motion"));
+ enableTypeBasedAliasAnalysis = !flags.contains(
+ QLatin1String("--no_tbaa"));
+ enableStaticClustering = !flags.contains(
+ QLatin1String("--no_clustering"));
+ enableInstructionScheduling = !flags.contains(
+ QLatin1String("--no_scheduling"));
+ enableVectorization = flags.contains(
+ QLatin1String("--vectorize"));
+ disableSizeConstraints = flags.contains(
+ QLatin1String("--no_size_constraints"));
+ }
+
+ Strategy optimizationStrategy = StrategyBalanced;
+ Level optimizationLevel = LevelNone;
+ LevelSlave optimizationLevelSlave = LevelSlave0;
+ // Eight bit-field flags on "enabled optimizations" widget.
+ int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination.
+ int enableLoopUnroll = 0; // Loop unrolling.
+ int enableFunctionInlining = 0; // Function inlining.
+ int enableCodeMotion = 0; // Code motion.
+ int enableTypeBasedAliasAnalysis = 0; // Type-based alias analysis.
+ int enableStaticClustering = 0; // Static clustering.
+ int enableInstructionScheduling = 0; // Instruction scheduling.
+ int enableVectorization = 0; // Vectorization.
+
+ // Separate "no size constraints" checkbox.
+ int disableSizeConstraints = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const QString &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int treatWarningsAsErrors = 0;
+};
+
+// Code page options.
+
+struct CodePageOptions final
+{
+ enum ProcessorMode {
+ CpuArmMode,
+ CpuThumbMode
+ };
+
+ explicit CodePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ const QString cpuModeValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--cpu_mode"));
+ if (cpuModeValue == QLatin1String("thumb"))
+ cpuMode = CodePageOptions::CpuThumbMode;
+ else if (cpuModeValue == QLatin1String("arm"))
+ cpuMode = CodePageOptions::CpuArmMode;
+
+ generateReadOnlyPosIndependentCode = flags.contains(
+ QLatin1String("--ropi"));
+ generateReadWritePosIndependentCode = flags.contains(
+ QLatin1String("--rwpi"));
+ disableDynamicReadWriteInitialization = flags.contains(
+ QLatin1String("--no_rw_dynamic_init"));
+ disableCodeMemoryDataReads = flags.contains(
+ QLatin1String("--no_literal_pool"));
+ }
+
+ ProcessorMode cpuMode = CpuThumbMode;
+ int generateReadOnlyPosIndependentCode = 0;
+ int generateReadWritePosIndependentCode = 0;
+ int disableDynamicReadWriteInitialization = 0;
+ int disableCodeMemoryDataReads = 0;
+};
+
+} // namespace
+
+// ArmCompilerSettingsGroup
+
+ArmCompilerSettingsGroup::ArmCompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("ICCARM"));
+ setArchiveVersion(kCompilerArchiveVersion);
+ setDataVersion(kCompilerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildOutputPage(qbsProduct);
+ buildLanguageOnePage(qbsProduct);
+ buildLanguageTwoPage(qbsProduct);
+ buildOptimizationsPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+ buildCodePage(qbsProduct);
+}
+
+void ArmCompilerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'CCDebugInfo' item (Generate debug info).
+ addOptionsGroup(QByteArrayLiteral("CCDebugInfo"),
+ {}, {opts.debugInfo});
+}
+
+void ArmCompilerSettingsGroup::buildLanguageOnePage(
+ const ProductData &qbsProduct)
+{
+ const LanguageOnePageOptions opts(qbsProduct);
+ // Add 'IccLang' item with 'auto-extension based'
+ // value (Language: C/C++/Auto).
+ addOptionsGroup(QByteArrayLiteral("IccLang"),
+ {}, {opts.languageExtension});
+ // Add 'IccCDialect' item (C dialect: c89/99/11).
+ addOptionsGroup(QByteArrayLiteral("IccCDialect"),
+ {}, {opts.cLanguageDialect});
+ // Add 'CCExt' item (Language conformance: IAR/relaxed/strict).
+ addOptionsGroup(QByteArrayLiteral("CCLangConformance"),
+ {}, {opts.languageConformance});
+ // Add 'IccExceptions2' item (Enable exceptions).
+ addOptionsGroup(QByteArrayLiteral("IccExceptions2"),
+ {}, {opts.enableExceptions});
+ // Add 'IccRTTI2' item (Enable RTTI).
+ addOptionsGroup(QByteArrayLiteral("IccRTTI2"),
+ {}, {opts.enableRtti});
+ // Add 'IccStaticDestr' item (Destroy static objects).
+ addOptionsGroup(QByteArrayLiteral("IccStaticDestr"),
+ {}, {opts.destroyStaticObjects});
+ // Add 'IccAllowVLA' item (Allow VLA).
+ addOptionsGroup(QByteArrayLiteral("IccAllowVLA"),
+ {}, {opts.allowVla});
+ // Add 'IccCppInlineSemantics' item (C++ inline semantics).
+ addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"),
+ {}, {opts.enableInlineSemantics});
+ // Add 'CCRequirePrototypes' item (Require prototypes).
+ addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"),
+ {}, {opts.requirePrototypes});
+}
+
+void ArmCompilerSettingsGroup::buildLanguageTwoPage(
+ const ProductData &qbsProduct)
+{
+ const LanguageTwoPageOptions opts(qbsProduct);
+ // Add 'CCSignedPlainChar' item (Plain char is: signed/unsigned).
+ addOptionsGroup(QByteArrayLiteral("CCSignedPlainChar"),
+ {}, {opts.plainCharacter});
+ // Add 'IccFloatSemantics' item
+ // (Floating-point semantic: strict/relaxed).
+ addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"),
+ {}, {opts.floatingPointSemantic});
+}
+
+void ArmCompilerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ const OptimizationsPageOptions opts(qbsProduct);
+ // Add 'CCOptStrategy', 'CCOptLevel'
+ // and 'CCOptLevelSlave' items (Level).
+ addOptionsGroup(QByteArrayLiteral("CCOptStrategy"),
+ {}, {opts.optimizationStrategy});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevel"),
+ {}, {opts.optimizationLevel});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"),
+ {}, {opts.optimizationLevelSlave});
+ // Add 'CCAllowList' item (Enabled optimizations: 6 check boxes).
+ const QString transformations = QStringLiteral("%1%2%3%4%5%6%7%8")
+ .arg(opts.enableCommonSubexpressionElimination)
+ .arg(opts.enableLoopUnroll)
+ .arg(opts.enableFunctionInlining)
+ .arg(opts.enableCodeMotion)
+ .arg(opts.enableTypeBasedAliasAnalysis)
+ .arg(opts.enableStaticClustering)
+ .arg(opts.enableInstructionScheduling)
+ .arg(opts.enableVectorization);
+ addOptionsGroup(QByteArrayLiteral("CCAllowList"),
+ {}, {transformations});
+ // Add 'CCOptimizationNoSizeConstraints' item (No size constraints).
+ addOptionsGroup(QByteArrayLiteral("CCOptimizationNoSizeConstraints"),
+ {}, {opts.disableSizeConstraints});
+}
+
+void ArmCompilerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'CCDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("CCDefines"),
+ {}, opts.defineSymbols);
+ // Add 'CCIncludePath2' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("CCIncludePath2"),
+ {}, opts.includePaths);
+}
+
+void ArmCompilerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"),
+ {}, {opts.treatWarningsAsErrors});
+}
+
+void ArmCompilerSettingsGroup::buildCodePage(
+ const ProductData &qbsProduct)
+{
+ const CodePageOptions opts(qbsProduct);
+ // Add 'IProcessorMode2' item (Processor mode: arm/thumb).
+ addOptionsGroup(QByteArrayLiteral("IProcessorMode2"),
+ {}, {opts.cpuMode});
+ // Add 'CCPosIndRopi' item (Code and read-only data "ropi").
+ addOptionsGroup(QByteArrayLiteral("CCPosIndRopi"),
+ {}, {opts.generateReadOnlyPosIndependentCode});
+ // Add 'CCPosIndRwpi' item (Read/write data "rwpi").
+ addOptionsGroup(QByteArrayLiteral("CCPosIndRwpi"), {},
+ {opts.generateReadWritePosIndependentCode});
+ // Add 'CCPosIndNoDynInit' item (No dynamic read/write initialization).
+ addOptionsGroup(QByteArrayLiteral("CCPosIndNoDynInit"),
+ {}, {opts.disableDynamicReadWriteInitialization});
+ // Add 'CCNoLiteralPool' item (No data reads in code memory).
+ addOptionsGroup(QByteArrayLiteral("CCNoLiteralPool"),
+ {}, {opts.disableCodeMemoryDataReads});
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h
new file mode 100644
index 000000000..6137bc976
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H
+#define QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmCompilerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit ArmCompilerSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildLanguageOnePage(const ProductData &qbsProduct);
+ void buildLanguageTwoPage(const ProductData &qbsProduct);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildCodePage(const ProductData &qbsProduct);
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp
new file mode 100644
index 000000000..d98dd0ebf
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp
@@ -0,0 +1,551 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armgeneralsettingsgroup_v8.h"
+
+#include "../../iarewutils.h"
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+constexpr int kGeneralArchiveVersion = 3;
+constexpr int kGeneralDataVersion = 30;
+
+namespace {
+
+struct CpuCoreEntry final
+{
+ enum CpuCoreCode {
+ Arm7tdmi = 0,
+ Arm7tdmis = 1,
+ Arm710t = 2,
+ Arm720t = 3,
+ Arm740t = 4,
+ Arm7ejs = 5,
+ Arm9tdmi = 6,
+ Arm920t = 7,
+ Arm922t = 8,
+ Arm940t = 9,
+ Arm9e = 10,
+ Arm9es = 11,
+ Arm926ejs = 12,
+ Arm946es = 13,
+ Arm966es = 14,
+ Arm968es = 15,
+ Arm10e = 16,
+ Arm1020e = 17,
+ Arm1022e = 18,
+ Arm1026ejs = 19,
+ Arm1136j = 20,
+ Arm1136js = 21,
+ Arm1176j = 24,
+ Arm1176js = 25,
+ Xscale = 32,
+ XscaleIr7 = 33,
+ CortexM0 = 34,
+ CortexM0Plus = 35,
+ CortexM1 = 36,
+ CortexMs1 = 37,
+ CortexM3 = 38,
+ CortexM4 = 39,
+ CortexM7 = 41,
+ CortexR4 = 42,
+ CortexR5 = 44,
+ CortexR7 = 46,
+ CortexR8 = 48,
+ CortexR52 = 49,
+ CortexA5 = 50,
+ CortexA7 = 52,
+ CortexA8 = 53,
+ CortexA9 = 54,
+ CortexA15 = 55,
+ CortexA17 = 56,
+ CortexM23 = 58,
+ CortexM33 = 59
+ };
+
+ // Required to compile in MSVC2015.
+ CpuCoreEntry(CpuCoreCode cc, QByteArray tf)
+ : coreCode(cc), targetFlag(std::move(tf))
+ {}
+
+ CpuCoreCode coreCode = Arm7tdmi;
+ QByteArray targetFlag;
+};
+
+// Dictionary of known ARM CPU cores and its compiler options.
+static const CpuCoreEntry cpusDict[] = {
+ {CpuCoreEntry::Arm7tdmi, "arm7tdmi"}, // same as 'sc100'
+ {CpuCoreEntry::Arm7tdmis, "arm7tdmi-s"},
+ {CpuCoreEntry::Arm710t, "arm710t"},
+ {CpuCoreEntry::Arm720t, "arm720t"},
+ {CpuCoreEntry::Arm740t, "arm740t"},
+ {CpuCoreEntry::Arm7ejs, "arm7ej-s"},
+ {CpuCoreEntry::Arm9tdmi, "arm9tdmi"},
+ {CpuCoreEntry::Arm920t, "arm920t"},
+ {CpuCoreEntry::Arm922t, "arm922t"},
+ {CpuCoreEntry::Arm940t, "arm940t"},
+ {CpuCoreEntry::Arm9e, "arm9e"},
+ {CpuCoreEntry::Arm9es, "arm9e-s"},
+ {CpuCoreEntry::Arm926ejs, "arm926ej-s"},
+ {CpuCoreEntry::Arm946es, "arm946e-s"},
+ {CpuCoreEntry::Arm966es, "arm966e-s"},
+ {CpuCoreEntry::Arm968es, "arm968e-s"},
+ {CpuCoreEntry::Arm10e, "arm10e"},
+ {CpuCoreEntry::Arm1020e, "arm1020e"},
+ {CpuCoreEntry::Arm1022e, "arm1022e"},
+ {CpuCoreEntry::Arm1026ejs, "arm1026ej-s"},
+ {CpuCoreEntry::Arm1136j, "arm1136j"},
+ {CpuCoreEntry::Arm1136js, "arm1136j-s"},
+ {CpuCoreEntry::Arm1176j, "arm1176j"},
+ {CpuCoreEntry::Arm1176js, "arm1176j-s"},
+ {CpuCoreEntry::Xscale, "xscale"},
+ {CpuCoreEntry::XscaleIr7, "xscale-ir7"},
+ {CpuCoreEntry::CortexM0, "cortex-m0"},
+ {CpuCoreEntry::CortexM0Plus, "cortex-m0+"}, // same as 'sc000'
+ {CpuCoreEntry::CortexM1, "cortex-m1"},
+ {CpuCoreEntry::CortexMs1, "cortex-ms1"},
+ {CpuCoreEntry::CortexM3, "cortex-m3"}, // same as 'sc300'
+ {CpuCoreEntry::CortexM4, "cortex-m4"},
+ {CpuCoreEntry::CortexM7, "cortex-m7"},
+ {CpuCoreEntry::CortexR4, "cortex-r4"},
+ {CpuCoreEntry::CortexR5, "cortex-r5"},
+ {CpuCoreEntry::CortexR7, "cortex-r7"},
+ {CpuCoreEntry::CortexR8, "cortex-r8"},
+ {CpuCoreEntry::CortexR52, "cortex-r52"},
+ {CpuCoreEntry::CortexA5, "cortex-a5"},
+ {CpuCoreEntry::CortexA7, "cortex-a7"},
+ {CpuCoreEntry::CortexA8, "cortex-a8"},
+ {CpuCoreEntry::CortexA9, "cortex-a9"},
+ {CpuCoreEntry::CortexA15, "cortex-a15"},
+ {CpuCoreEntry::CortexA17, "cortex-a17"},
+ {CpuCoreEntry::CortexM23, "cortex-m23"},
+ {CpuCoreEntry::CortexM33, "cortex-m33"},
+};
+
+struct FpuCoreEntry final
+{
+ enum FpuRegistersCount {
+ NoFpuRegisters,
+ Fpu16Registers,
+ Fpu32Registers
+ };
+
+ enum FpuCoreCode {
+ NoVfp = 0,
+ Vfp2 = 2,
+ Vfp3d16 = 3,
+ Vfp3 = 3,
+ Vfp4sp = 4,
+ Vfp4d16 = 5,
+ Vfp4 = 5,
+ Vfp5sp = 6,
+ Vfp5d16 = 7,
+ Vfp9s = 8
+ };
+
+ // Required to compile in MSVC2015.
+ FpuCoreEntry(FpuCoreCode cc, FpuRegistersCount rc,
+ QByteArray tf)
+ : coreCode(cc), regsCount(rc), targetFlag(std::move(tf))
+ {}
+
+ FpuCoreCode coreCode = NoVfp;
+ FpuRegistersCount regsCount = NoFpuRegisters;
+ QByteArray targetFlag;
+};
+
+// Dictionary of known ARM FPU cores and its compiler options.
+static const FpuCoreEntry fpusDict[] = {
+ {FpuCoreEntry::Vfp2, FpuCoreEntry::NoFpuRegisters, "vfpv2"},
+ {FpuCoreEntry::Vfp3d16, FpuCoreEntry::Fpu16Registers, "vfpv3_d16"},
+ {FpuCoreEntry::Vfp3, FpuCoreEntry::Fpu32Registers, "vfpv3"},
+ {FpuCoreEntry::Vfp4sp, FpuCoreEntry::Fpu16Registers, "vfpv4_sp"},
+ {FpuCoreEntry::Vfp4d16, FpuCoreEntry::Fpu16Registers, "vfpv4_d16"},
+ {FpuCoreEntry::Vfp4, FpuCoreEntry::Fpu32Registers, "vfpv4"},
+ {FpuCoreEntry::Vfp5sp, FpuCoreEntry::Fpu16Registers, "vfpv5_sp"},
+ {FpuCoreEntry::Vfp5d16, FpuCoreEntry::Fpu16Registers, "vfpv5_d16"},
+ {FpuCoreEntry::Vfp9s, FpuCoreEntry::NoFpuRegisters, "vfp9-s"},
+};
+
+// Target page options.
+
+struct TargetPageOptions final
+{
+ enum Endianness {
+ LittleEndian,
+ BigEndian
+ };
+
+ explicit TargetPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags")});
+ // Detect target CPU code.
+ const QString cpuValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--cpu"))
+ .toLower();
+ const auto cpuEnd = std::cend(cpusDict);
+ const auto cpuIt = std::find_if(std::cbegin(cpusDict), cpuEnd,
+ [cpuValue](
+ const CpuCoreEntry &entry) {
+ return entry.targetFlag == cpuValue.toLatin1();
+ });
+ if (cpuIt != cpuEnd)
+ targetCpu = cpuIt->coreCode;
+ // Detect target FPU code.
+ const QString fpuValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--fpu"))
+ .toLower();
+ const auto fpuEnd = std::cend(fpusDict);
+ const auto fpuIt = std::find_if(std::cbegin(fpusDict), fpuEnd,
+ [fpuValue](
+ const FpuCoreEntry &entry) {
+ return entry.targetFlag == fpuValue.toLatin1();
+ });
+ if (fpuIt != fpuEnd) {
+ targetFpu = fpuIt->coreCode;
+ targetFpuRegs = fpuIt->regsCount;
+ }
+ // Detect endian.
+ const QString prop = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("endianness"));
+ if (prop == QLatin1String("big"))
+ endianness = TargetPageOptions::BigEndian;
+ else if (prop == QLatin1String("little"))
+ endianness = TargetPageOptions::LittleEndian;
+ }
+
+ CpuCoreEntry::CpuCoreCode targetCpu = CpuCoreEntry::Arm7tdmi;
+ FpuCoreEntry::FpuCoreCode targetFpu = FpuCoreEntry::NoVfp;
+ FpuCoreEntry::FpuRegistersCount targetFpuRegs = FpuCoreEntry::NoFpuRegisters;
+ Endianness endianness = LittleEndian;
+};
+
+// Library 1 page options.
+
+struct LibraryOnePageOptions final
+{
+ enum PrintfFormatter {
+ PrintfAutoFormatter,
+ PrintfFullFormatter,
+ PrintfLargeFormatter,
+ PrintfSmallFormatter,
+ PrintfTinyFormatter
+ };
+
+ enum ScanfFormatter {
+ ScanfAutoFormatter,
+ ScanfFullFormatter,
+ ScanfLargeFormatter,
+ ScanfSmallFormatter
+ };
+
+ explicit LibraryOnePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) {
+ if (*flagIt != QLatin1String("--redirect"))
+ continue;
+ ++flagIt;
+ if (flagIt->startsWith(QLatin1String("_printf="),
+ Qt::CaseInsensitive)) {
+ const QString prop = flagIt->split(
+ QLatin1Char('=')).at(1).toLower();
+ if (prop == QLatin1String("_printffullnomb"))
+ printfFormatter = LibraryOnePageOptions::PrintfFullFormatter;
+ else if (prop == QLatin1String("_printflargenomb"))
+ printfFormatter = LibraryOnePageOptions::PrintfLargeFormatter;
+ else if (prop == QLatin1String("_printfsmallnomb"))
+ printfFormatter = LibraryOnePageOptions::PrintfSmallFormatter;
+ else if (prop == QLatin1String("_printftiny"))
+ printfFormatter = LibraryOnePageOptions::PrintfTinyFormatter;
+ } else if (flagIt->startsWith(QLatin1String("_scanf="),
+ Qt::CaseInsensitive)) {
+ const QString prop = flagIt->split(
+ QLatin1Char('=')).at(1).toLower();;
+ if (prop == QLatin1String("_scanffullnomb"))
+ scanfFormatter = LibraryOnePageOptions::ScanfFullFormatter;
+ else if (prop == QLatin1String("_scanflargenomb"))
+ scanfFormatter = LibraryOnePageOptions::ScanfLargeFormatter;
+ else if (prop == QLatin1String("_scanfsmallnomb"))
+ scanfFormatter = LibraryOnePageOptions::ScanfSmallFormatter;
+ }
+ }
+ }
+
+ PrintfFormatter printfFormatter = PrintfAutoFormatter;
+ ScanfFormatter scanfFormatter = ScanfAutoFormatter;
+};
+
+// Library 2 page options.
+
+struct LibraryTwoPageOptions final
+{
+ enum HeapType {
+ AutomaticHeap,
+ AdvancedHeap,
+ BasicHeap,
+ NoFreeHeap
+ };
+
+ explicit LibraryTwoPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ if (flags.contains(QLatin1String("--advanced_heap")))
+ heapType = LibraryTwoPageOptions::AdvancedHeap;
+ else if (flags.contains(QLatin1String("--basic_heap")))
+ heapType = LibraryTwoPageOptions::BasicHeap;
+ else if (flags.contains(QLatin1String("--no_free_heap")))
+ heapType = LibraryTwoPageOptions::NoFreeHeap;
+ else
+ heapType = LibraryTwoPageOptions::AutomaticHeap;
+ }
+
+ HeapType heapType = AutomaticHeap;
+};
+
+// Library configuration page options.
+
+struct LibraryConfigPageOptions final
+{
+ enum RuntimeLibrary {
+ NoLibrary,
+ NormalLibrary,
+ FullLibrary,
+ CustomLibrary
+ };
+
+ enum ThreadSupport {
+ NoThread,
+ EnableThread
+ };
+
+ enum LowLevelInterface {
+ NoInterface,
+ SemihostedInterface
+ };
+
+ explicit LibraryConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ const QFileInfo dlibFileInfo(IarewUtils::flagValue(
+ flags, QStringLiteral("--dlib_config")));
+ if (!dlibFileInfo.exists()) {
+ dlibType = LibraryConfigPageOptions::NoLibrary;
+ } else {
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QString dlibFilePath = dlibFileInfo.absoluteFilePath();
+ if (dlibFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ if (dlibFilePath.endsWith(QLatin1String("dlib_config_normal.h"),
+ Qt::CaseInsensitive)) {
+ dlibType = LibraryConfigPageOptions::NormalLibrary;
+ } else if (dlibFilePath.endsWith(
+ QLatin1String("dlib_config_full.h"),
+ Qt::CaseInsensitive)) {
+ dlibType = LibraryConfigPageOptions::FullLibrary;
+ } else {
+ dlibType = LibraryConfigPageOptions::CustomLibrary;
+ }
+
+ dlibConfigPath = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, dlibFilePath);
+ } else {
+ dlibType = LibraryConfigPageOptions::CustomLibrary;
+ dlibConfigPath = IarewUtils::projectRelativeFilePath(
+ baseDirectory, dlibFilePath);
+ }
+ }
+
+ threadSupport = flags.contains(QLatin1String("--threaded_lib"))
+ ? LibraryConfigPageOptions::EnableThread
+ : LibraryConfigPageOptions::NoThread;
+ lowLevelInterface = flags.contains(QLatin1String("--semihosting"))
+ ? LibraryConfigPageOptions::SemihostedInterface
+ : LibraryConfigPageOptions::NoInterface;
+ }
+
+ RuntimeLibrary dlibType = NoLibrary;
+ QString dlibConfigPath;
+ ThreadSupport threadSupport = NoThread;
+ LowLevelInterface lowLevelInterface = NoInterface;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ binaryType = IarewUtils::outputBinaryType(qbsProduct);
+ binaryDirectory = gen::utils::binaryOutputDirectory(
+ baseDirectory, qbsProduct);
+ objectDirectory = gen::utils::objectsOutputDirectory(
+ baseDirectory, qbsProduct);
+ listingDirectory = gen::utils::listingOutputDirectory(
+ baseDirectory, qbsProduct);
+ }
+
+ IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType;
+ QString binaryDirectory;
+ QString objectDirectory;
+ QString listingDirectory;
+};
+
+} // namespace
+
+// ArmGeneralSettingsGroup
+
+ArmGeneralSettingsGroup::ArmGeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("General"));
+ setArchiveVersion(kGeneralArchiveVersion);
+ setDataVersion(kGeneralDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildTargetPage(qbsProduct);
+ buildLibraryOptionsOnePage(qbsProduct);
+ buildLibraryOptionsTwoPage(qbsProduct);
+ buildLibraryConfigPage(buildRootDirectory, qbsProduct);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void ArmGeneralSettingsGroup::buildTargetPage(
+ const ProductData &qbsProduct)
+{
+ const TargetPageOptions opts(qbsProduct);
+ // Add 'GBECoreSlave', 'CoreVariant', 'GFPUCoreSlave2' items
+ // (Processor variant chooser).
+ addOptionsGroup(QByteArrayLiteral("GBECoreSlave"),
+ {26}, {opts.targetCpu});
+ addOptionsGroup(QByteArrayLiteral("CoreVariant"),
+ {26}, {opts.targetCpu});
+ addOptionsGroup(QByteArrayLiteral("GFPUCoreSlave2"),
+ {26}, {opts.targetCpu});
+ // Add 'FPU2', 'NrRegs' item (Floating point settings chooser).
+ addOptionsGroup(QByteArrayLiteral("FPU2"),
+ {0}, {opts.targetFpu});
+ addOptionsGroup(QByteArrayLiteral("NrRegs"),
+ {0}, {opts.targetFpuRegs});
+ // Add 'GEndianMode' item (Endian mode chooser).
+ addOptionsGroup(QByteArrayLiteral("GEndianMode"),
+ {}, {opts.endianness});
+}
+
+void ArmGeneralSettingsGroup::buildLibraryOptionsOnePage(
+ const ProductData &qbsProduct)
+{
+ const LibraryOnePageOptions opts(qbsProduct);
+ // Add 'OGPrintfVariant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("OGPrintfVariant"),
+ {}, {opts.printfFormatter});
+ // Add 'OGScanfVariant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("OGScanfVariant"),
+ {}, {opts.scanfFormatter});
+}
+
+void ArmGeneralSettingsGroup::buildLibraryOptionsTwoPage(
+ const ProductData &qbsProduct)
+{
+ const LibraryTwoPageOptions opts(qbsProduct);
+ // Add 'OgLibHeap' item (Heap selection:
+ // auto/advanced/basic/nofree).
+ addOptionsGroup(QByteArrayLiteral("OgLibHeap"),
+ {}, {opts.heapType});
+}
+
+void ArmGeneralSettingsGroup::buildLibraryConfigPage(
+ const QString baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const LibraryConfigPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GRuntimeLibSelect', 'GRuntimeLibSelectSlave'
+ // and 'RTConfigPath2' items
+ // (Link with runtime: none/normal/full/custom).
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"),
+ {}, {opts.dlibType});
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"),
+ {}, {opts.dlibType});
+ addOptionsGroup(QByteArrayLiteral("RTConfigPath2"),
+ {}, {opts.dlibConfigPath});
+ // Add 'GRuntimeLibThreads'item
+ // (Enable thread support in library).
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibThreads"),
+ {}, {opts.threadSupport});
+ // Add 'GenLowLevelInterface' item (Library low-level
+ // interface: none/semihosted/breakpoint).
+ addOptionsGroup(QByteArrayLiteral("GenLowLevelInterface"),
+ {}, {opts.lowLevelInterface});
+}
+
+void ArmGeneralSettingsGroup::buildOutputPage(
+ const QString baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GOutputBinary' item
+ // (Output file: executable/library).
+ addOptionsGroup(QByteArrayLiteral("GOutputBinary"),
+ {}, {opts.binaryType});
+ // Add 'ExePath' item
+ // (Executable/binaries output directory).
+ addOptionsGroup(QByteArrayLiteral("ExePath"),
+ {}, {opts.binaryDirectory});
+ // Add 'ObjPath' item
+ // (Object files output directory).
+ addOptionsGroup(QByteArrayLiteral("ObjPath"),
+ {}, {opts.objectDirectory});
+ // Add 'ListPath' item
+ // (List files output directory).
+ addOptionsGroup(QByteArrayLiteral("ListPath"),
+ {}, {opts.listingDirectory});
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h
new file mode 100644
index 000000000..420e98008
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMGENERALSETTINGSGROUP_V8_H
+#define QBS_IAREWARMGENERALSETTINGSGROUP_V8_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmGeneralSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit ArmGeneralSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildTargetPage(const ProductData &qbsProduct);
+ void buildLibraryOptionsOnePage(const ProductData &qbsProduct);
+ void buildLibraryOptionsTwoPage(const ProductData &qbsProduct);
+ void buildLibraryConfigPage(const QString baseDirectory,
+ const ProductData &qbsProduct);
+ void buildOutputPage(const QString baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMGENERALSETTINGSGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp
new file mode 100644
index 000000000..1fdbce5ce
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp
@@ -0,0 +1,489 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "armlinkersettingsgroup_v8.h"
+
+#include "../../iarewutils.h"
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+constexpr int kLinkerArchiveVersion = 0;
+constexpr int kLinkerDataVersion = 20;
+
+namespace {
+
+// Config page options.
+
+struct ConfigPageOptions final
+{
+ explicit ConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ // Accumulate config definitions (if exists).
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ configDefines = IarewUtils::flagValues(
+ flags, QStringLiteral("--config_def"));
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+
+ // Enumerate all product linker config files
+ // (which are set trough 'linkerscript' tag).
+ const auto qbsGroups = qbsProduct.groups();
+ for (const auto &qbsGroup : qbsGroups) {
+ if (!qbsGroup.isEnabled())
+ continue;
+ const auto qbsArtifacts = qbsGroup.sourceArtifacts();
+ for (const auto &qbsArtifact : qbsArtifacts) {
+ const auto qbsTags = qbsArtifact.fileTags();
+ if (!qbsTags.contains(QLatin1String("linkerscript")))
+ continue;
+ const QString fullConfigPath = qbsArtifact.filePath();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ configFilePaths.push_back(path);
+ }
+ }
+ }
+
+ // Enumerate all product linker config files
+ // (which are set trough '--config' option).
+ const QVariantList configPathValues = IarewUtils::flagValues(
+ flags, QStringLiteral("--config"));
+ for (const auto &configPathValue : configPathValues) {
+ const QString fullConfigPath = configPathValue.toString();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList configFilePaths;
+ QVariantList configDefines;
+};
+
+// Library page options.
+
+struct LibraryPageOptions final
+{
+ explicit LibraryPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+
+ entryPoint = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("entryPoint"));
+
+ // Add libraries search paths.
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList libraryPaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("libraryPaths")});
+ for (const QString &libraryPath : libraryPaths) {
+ const QFileInfo libraryPathInfo(libraryPath);
+ const QString fullLibrarySearchPath =
+ libraryPathInfo.absoluteFilePath();
+ if (fullLibrarySearchPath.startsWith(
+ toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory,fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ }
+ }
+
+ // Add static libraries paths.
+ const QStringList staticLibrariesProps =
+ gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ for (const QString &staticLibrary : staticLibrariesProps) {
+ const QFileInfo staticLibraryInfo(staticLibrary);
+ if (staticLibraryInfo.isAbsolute()) {
+ const QString fullStaticLibraryPath =
+ staticLibraryInfo.absoluteFilePath();
+ if (fullStaticLibraryPath.startsWith(
+ toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ }
+ } else {
+ staticLibraries.push_back(staticLibrary);
+ }
+ }
+
+ // Add static libraries from product dependencies.
+ for (const ProductData &qbsProductDep : qbsProductDeps) {
+ const QString depBinaryPath = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory,
+ qbsProductDep);
+ staticLibraries.push_back(depBinaryPath);
+ }
+
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ enableRuntimeLibsSearch = !flags.contains(
+ QLatin1String("--no_library_search"));
+ }
+
+ QString entryPoint;
+ QVariantList staticLibraries;
+ QVariantList librarySearchPaths;
+ int enableRuntimeLibsSearch = 0;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ debugInfo = !flags.contains(QLatin1String("--strip"));
+ outputFile = gen::utils::targetBinary(qbsProduct);
+ }
+
+ int debugInfo = 0;
+ QString outputFile;
+};
+
+// Input page options.
+
+struct InputPageOptions final
+{
+ explicit InputPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ keepSymbols = IarewUtils::flagValues(flags, QStringLiteral("--keep"));
+ }
+
+ QVariantList keepSymbols;
+};
+
+// List page options.
+
+struct ListPageOptions final
+{
+ enum ListingAction {
+ NoListing,
+ GenerateListing
+ };
+
+ explicit ListPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ generateMap = gen::utils::cppBooleanModuleProperty(
+ qbsProps, QStringLiteral("generateMapFile"))
+ ? ListPageOptions::GenerateListing
+ : ListPageOptions::NoListing;
+ }
+
+ ListingAction generateMap = GenerateListing;
+};
+
+// Optimizations page options.
+
+struct OptimizationsPageOptions final
+{
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ inlineSmallRoutines = flags.contains(QLatin1String("--inline"));
+ mergeDuplicateSections = flags.contains(
+ QLatin1String("--merge_duplicate_sections"));
+ virtualFuncElimination = flags.contains(QLatin1String("--vfe"));
+ }
+
+ int inlineSmallRoutines = 0;
+ int mergeDuplicateSections = 0;
+ int virtualFuncElimination = 0;
+};
+
+// Advanced page options.
+
+struct AdvancedPageOptions final
+{
+ explicit AdvancedPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ allowExceptions = !flags.contains(QLatin1String("--no_exceptions"));
+ }
+
+ int allowExceptions = 0;
+};
+
+// Defines page options.
+
+struct DefinesPageOptions final
+{
+ explicit DefinesPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ defineSymbols = IarewUtils::flagValues(
+ flags, QStringLiteral("--define_symbol"));
+ }
+
+ QVariantList defineSymbols;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int treatWarningsAsErrors = 0;
+};
+
+} // namespace
+
+// ArmLinkerSettingsGroup
+
+ArmLinkerSettingsGroup::ArmLinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ setName(QByteArrayLiteral("ILINK"));
+ setArchiveVersion(kLinkerArchiveVersion);
+ setDataVersion(kLinkerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildConfigPage(buildRootDirectory, qbsProduct);
+ buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps);
+ buildOutputPage(qbsProduct);
+ buildInputPage(qbsProduct);
+ buildListPage(qbsProduct);
+ buildOptimizationsPage(qbsProduct);
+ buildAdvancedPage(qbsProduct);
+ buildDefinesPage(qbsProduct);
+
+ // Should be called as latest stage!
+ buildExtraOptionsPage(qbsProduct);
+}
+
+void ArmLinkerSettingsGroup::buildConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ ConfigPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'IlinkConfigDefines' item
+ // (Configuration file symbol definitions).
+ addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"),
+ {}, opts.configDefines);
+
+ if (opts.configFilePaths.count() > 0) {
+ // Note: IAR IDE does not allow to specify a multiple config files,
+ // although the IAR linker support it. So, we use followig 'trick':
+ // we take a first config file and to add it as usual to required items;
+ // and then an other remainders we forward to the "Extra options page".
+ const QVariant configPath = opts.configFilePaths.takeFirst();
+ // Add 'IlinkIcfOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"),
+ {}, {1});
+ // Add 'IlinkIcfFile' item (Linker configuration file).
+ addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"),
+ {}, {configPath});
+
+ // Add remainder configuration files to the "Extra options page".
+ if (!opts.configFilePaths.isEmpty()) {
+ for (QVariant &configPath : opts.configFilePaths)
+ configPath = QLatin1String("--config ")
+ + configPath.toString();
+
+ m_extraOptions << opts.configFilePaths;
+ }
+ }
+}
+
+void ArmLinkerSettingsGroup::buildLibraryPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps);
+ // Add 'IlinkOverrideProgramEntryLabel' item
+ // (Override default program entry).
+ addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"),
+ {}, {1});
+ const int select = opts.entryPoint.isEmpty() ? 1 : 0;
+ addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"),
+ {}, {select});
+ // Add 'IlinkProgramEntryLabel' item (Entry point name).
+ addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"),
+ {}, {opts.entryPoint});
+
+ if (!opts.staticLibraries.isEmpty()) {
+ // Add 'IlinkAdditionalLibs' item (Additional libraries).
+ addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"),
+ {}, opts.staticLibraries);
+ }
+
+ // Add 'IlinkAutoLibEnable' item
+ // (Automatic runtime library selection).
+ addOptionsGroup(QByteArrayLiteral("IlinkAutoLibEnable"),
+ {}, {opts.enableRuntimeLibsSearch});
+
+ // Add library searh directories to the
+ // "Extra options page", because IAR IDE
+ // has not other options to add this paths.
+ for (QVariant &libraryPath : opts.librarySearchPaths)
+ libraryPath = QLatin1String("-L ") + libraryPath.toString();
+
+ m_extraOptions << opts.librarySearchPaths;
+}
+
+void ArmLinkerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'IlinkDebugInfoEnable' item
+ // (Include debug information in output).
+ addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"),
+ {}, {opts.debugInfo});
+ // Add 'IlinkOutputFile' item (Output filename).
+ addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"),
+ {}, {opts.outputFile});
+}
+
+void ArmLinkerSettingsGroup::buildInputPage(
+ const ProductData &qbsProduct)
+{
+ const InputPageOptions opts(qbsProduct);
+ // Add 'IlinkKeepSymbols' item ().
+ addOptionsGroup(QByteArrayLiteral("IlinkKeepSymbols"),
+ {}, opts.keepSymbols);
+}
+
+void ArmLinkerSettingsGroup::buildListPage(
+ const ProductData &qbsProduct)
+{
+ const ListPageOptions opts(qbsProduct);
+ // Add 'IlinkMapFile' item (Generate linker map file).
+ addOptionsGroup(QByteArrayLiteral("IlinkMapFile"),
+ {}, {opts.generateMap});
+}
+
+void ArmLinkerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ const OptimizationsPageOptions opts(qbsProduct);
+ // Add 'IlinkOptInline' item (Inline small routines).
+ addOptionsGroup(QByteArrayLiteral("IlinkOptInline"),
+ {}, {opts.inlineSmallRoutines});
+ // Add 'IlinkOptMergeDuplSections'item
+ // (Merge duplicate sections).
+ addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"),
+ {}, {opts.mergeDuplicateSections});
+ // Add 'IlinkOptUseVfe' item
+ // (Perform C++ virtual functions elimination).
+ addOptionsGroup(QByteArrayLiteral("IlinkOptUseVfe"),
+ {}, {opts.virtualFuncElimination});
+}
+
+void ArmLinkerSettingsGroup::buildAdvancedPage(
+ const ProductData &qbsProduct)
+{
+ const AdvancedPageOptions opts(qbsProduct);
+ // Add 'IlinkOptExceptionsAllow' item (Allow C++ exceptions).
+ addOptionsGroup(QByteArrayLiteral("IlinkOptExceptionsAllow"),
+ {}, {opts.allowExceptions});
+}
+
+void ArmLinkerSettingsGroup::buildDefinesPage(
+ const ProductData &qbsProduct)
+{
+ const DefinesPageOptions opts(qbsProduct);
+ // Add 'IlinkDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("IlinkDefines"),
+ {}, {opts.defineSymbols});
+}
+
+void ArmLinkerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'IlinkWarningsAreErrors' item
+ // (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"),
+ {}, {opts.treatWarningsAsErrors});
+}
+
+void ArmLinkerSettingsGroup::buildExtraOptionsPage(
+ const ProductData &qbsProduct)
+{
+ Q_UNUSED(qbsProduct)
+
+ // Add 'IlinkUseExtraOptions' and 'IlinkExtraOptions' items.
+ addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"),
+ {}, {1});
+ addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"),
+ {}, m_extraOptions);
+}
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h
new file mode 100644
index 000000000..e86297e6e
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWARMLINKERSETTINGSGROUP_V8_H
+#define QBS_IAREWARMLINKERSETTINGSGROUP_V8_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace arm {
+namespace v8 {
+
+class ArmLinkerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit ArmLinkerSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildLibraryPage(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildInputPage(const ProductData &qbsProduct);
+ void buildListPage(const ProductData &qbsProduct);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+ void buildAdvancedPage(const ProductData &qbsProduct);
+ void buildDefinesPage(const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildExtraOptionsPage(const ProductData &qbsProduct);
+
+ QVariantList m_extraOptions;
+};
+
+} // namespace v8
+} // namespace arm
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWARMLINKERSETTINGSGROUP_V8_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp
new file mode 100644
index 000000000..a3babc1d1
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrarchiversettingsgroup_v7.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+constexpr int kArchiverArchiveVersion = 2;
+constexpr int kArchiverDataVersion = 0;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ outputFile = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory, qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+} // namespace
+
+// AvrArchiverSettingsGroup
+
+AvrArchiverSettingsGroup::AvrArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("XAR"));
+ setArchiveVersion(kArchiverArchiveVersion);
+ setDataVersion(kArchiverDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void AvrArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'XAROutOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("XAROutOverride"),
+ {}, {1});
+ // Add 'OutputFile' item (Output filename).
+ addOptionsGroup(QByteArrayLiteral("OutputFile"),
+ {}, {opts.outputFile});
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h
new file mode 100644
index 000000000..2ff667e1d
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H
+#define QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrArchiverSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit AvrArchiverSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp
new file mode 100644
index 000000000..ecb5400ea
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrassemblersettingsgroup_v7.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+constexpr int kAssemblerArchiveVersion = 5;
+constexpr int kAssemblerDataVersion = 11;
+
+namespace {
+
+// Language page options.
+
+struct LanguagePageOptions final
+{
+ enum MacroQuoteCharacter {
+ AngleBracketsQuote,
+ RoundBracketsQuote,
+ SquareBracketsQuote,
+ FigureBracketsQuote
+ };
+
+ explicit LanguagePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("assemblerFlags")});
+ enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+"));
+ enableMultibyteSupport = flags.contains(QLatin1String("-n"));
+
+ if (flags.contains(QLatin1String("-M<>")))
+ macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote;
+ else if (flags.contains(QLatin1String("-M()")))
+ macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote;
+ else if (flags.contains(QLatin1String("-M[]")))
+ macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote;
+ else if (flags.contains(QLatin1String("-M{}")))
+ macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote;
+ }
+
+ MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote;
+ int enableSymbolsCaseSensitive = 0;
+ int enableMultibyteSupport = 0;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const auto &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString warningLevel = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ if (warningLevel == QLatin1String("all")) {
+ enableWarnings = 0;
+ enableAllWarnings = 0;
+ } else if (warningLevel == QLatin1String("none")) {
+ enableWarnings = 1;
+ enableAllWarnings = 0;
+ } else {
+ enableWarnings = 0;
+ enableAllWarnings = 1;
+ }
+ }
+
+ int enableWarnings = 0;
+ int enableAllWarnings = 0;
+};
+
+} // namespace
+
+// AvrAssemblerSettingsGroup
+
+AvrAssemblerSettingsGroup::AvrAssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("AAVR"));
+ setArchiveVersion(kAssemblerArchiveVersion);
+ setDataVersion(kAssemblerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildLanguagePage(qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void AvrAssemblerSettingsGroup::buildLanguagePage(
+ const ProductData &qbsProduct)
+{
+ const LanguagePageOptions opts(qbsProduct);
+ // Add 'ACaseSensitivity' item (User symbols are case sensitive).
+ addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"),
+ {}, {opts.enableSymbolsCaseSensitive});
+ // Add 'AsmMultiByteSupport' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("AsmMultiByteSupport"),
+ {}, {opts.enableMultibyteSupport});
+ // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>).
+ addOptionsGroup(QByteArrayLiteral("MacroChars"),
+ {0}, {opts.macroQuoteCharacter});
+}
+
+void AvrAssemblerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'CDebug' item (Generate debug information).
+ addOptionsGroup(QByteArrayLiteral("CDebug"),
+ {}, {opts.debugInfo});
+}
+
+void AvrAssemblerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'ADefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("ADefines"),
+ {}, opts.defineSymbols);
+ // Add 'AUserIncludes' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("ANewIncludes"),
+ {}, opts.includePaths);
+}
+
+void AvrAssemblerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'AWarnEnable' item (Enable/disable warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnEnable"),
+ {}, {opts.enableWarnings});
+ // Add 'AWarnWhat' item (Enable/disable all warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnWhat"),
+ {}, {opts.enableAllWarnings});
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h
new file mode 100644
index 000000000..608a42652
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H
+#define QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrAssemblerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit AvrAssemblerSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildLanguagePage(const ProductData &qbsProduct);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp
new file mode 100644
index 000000000..dbb5c6620
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrarchiversettingsgroup_v7.h"
+#include "avrassemblersettingsgroup_v7.h"
+#include "avrbuildconfigurationgroup_v7.h"
+#include "avrcompilersettingsgroup_v7.h"
+#include "avrgeneralsettingsgroup_v7.h"
+#include "avrlinkersettingsgroup_v7.h"
+
+#include "../../iarewtoolchainpropertygroup.h"
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+AvrBuildConfigurationGroup::AvrBuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup("configuration")
+{
+ // Append configuration name item.
+ const QString cfgName = gen::utils::buildConfigurationName(qbsProject);
+ appendProperty("name", cfgName);
+
+ // Apend toolchain name group item.
+ appendChild<IarewToolchainPropertyGroup>("AVR");
+
+ // Append debug info item.
+ const int debugBuild = gen::utils::debugInformation(qbsProduct);
+ appendProperty("debug", debugBuild);
+
+ // Append settings group items.
+ appendChild<AvrArchiverSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<AvrAssemblerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<AvrCompilerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<AvrGeneralSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<AvrLinkerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+}
+
+bool AvrBuildConfigurationGroupFactory::canCreate(
+ gen::utils::Architecture arch,
+ const Version &version) const
+{
+ return arch == gen::utils::Architecture::Avr
+ && version.majorVersion() == 7;
+}
+
+std::unique_ptr<gen::xml::PropertyGroup>
+AvrBuildConfigurationGroupFactory::create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const
+{
+ const auto group = new AvrBuildConfigurationGroup(
+ qbsProject, qbsProduct, qbsProductDeps);
+ return std::unique_ptr<AvrBuildConfigurationGroup>(group);
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h
new file mode 100644
index 000000000..618cef4c6
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H
+#define QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H
+
+#include <generators/generatorutils.h>
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrBuildConfigurationGroup final
+ : public gen::xml::PropertyGroup
+{
+private:
+ explicit AvrBuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+ friend class AvrBuildConfigurationGroupFactory;
+};
+
+class AvrBuildConfigurationGroupFactory final
+ : public gen::xml::PropertyGroupFactory
+{
+public:
+ bool canCreate(gen::utils::Architecture arch,
+ const Version &version) const final;
+
+ std::unique_ptr<gen::xml::PropertyGroup> create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const final;
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp
new file mode 100644
index 000000000..5c89c2d88
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp
@@ -0,0 +1,492 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrcompilersettingsgroup_v7.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+constexpr int kCompilerArchiveVersion = 6;
+constexpr int kCompilerDataVersion = 17;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ moduleType = flags.contains(QLatin1String("--library_module"))
+ ? OutputPageOptions::LibraryModule
+ : OutputPageOptions::ProgramModule;
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ disableErrorMessages = flags.contains(
+ QLatin1String("--no_ubrof_messages"));
+ }
+
+ int debugInfo = 0;
+ int disableErrorMessages = 0;
+ enum ModuleType { ProgramModule, LibraryModule};
+ ModuleType moduleType = ProgramModule;
+};
+
+// Language one page options.
+
+struct LanguageOnePageOptions final
+{
+ enum LanguageExtension {
+ CLanguageExtension,
+ CxxLanguageExtension,
+ AutoLanguageExtension
+ };
+
+ enum CLanguageDialect {
+ C89LanguageDialect,
+ C99LanguageDialect
+ };
+
+ enum CxxLanguageDialect {
+ EmbeddedCPlusPlus,
+ ExtendedEmbeddedCPlusPlus
+ };
+
+ enum LanguageConformance {
+ AllowIarExtension,
+ RelaxedStandard,
+ StrictStandard
+ };
+
+ explicit LanguageOnePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ // File extension based by default.
+ languageExtension = LanguageOnePageOptions::AutoLanguageExtension;
+ // C language dialect.
+ const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("cLanguageVersion")});
+ if (cLanguageVersion.contains(QLatin1String("c89")))
+ cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect;
+ else if (cLanguageVersion.contains(QLatin1String("c99")))
+ cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect;
+ // C++ language dialect.
+ if (flags.contains(QLatin1String("--ec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus;
+ else if (flags.contains(QLatin1String("--eec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus;
+ // Language conformance.
+ if (flags.contains(QLatin1String("-e")))
+ languageConformance = LanguageOnePageOptions::AllowIarExtension;
+ else if (flags.contains(QLatin1String("--strict")))
+ languageConformance = LanguageOnePageOptions::StrictStandard;
+ else
+ languageConformance = LanguageOnePageOptions::RelaxedStandard;
+
+ allowVla = flags.contains(QLatin1String("--vla"));
+ useCppInlineSemantics = flags.contains(
+ QLatin1String("--use_c++_inline"));
+ requirePrototypes = flags.contains(
+ QLatin1String("--require_prototypes"));
+ destroyStaticObjects = !flags.contains(
+ QLatin1String("--no_static_destruction"));
+ }
+
+ LanguageExtension languageExtension = AutoLanguageExtension;
+ CLanguageDialect cLanguageDialect = C89LanguageDialect;
+ CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus;
+ LanguageConformance languageConformance = AllowIarExtension;
+ int allowVla = 0;
+ int useCppInlineSemantics = 0;
+ int requirePrototypes = 0;
+ int destroyStaticObjects = 0;
+};
+
+// Language two page options.
+
+struct LanguageTwoPageOptions final
+{
+ enum PlainCharacter {
+ SignedCharacter,
+ UnsignedCharacter
+ };
+
+ enum FloatingPointSemantic {
+ StrictSemantic,
+ RelaxedSemantic
+ };
+
+ explicit LanguageTwoPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ plainCharacter = flags.contains(QLatin1String("--char_is_signed"))
+ ? LanguageTwoPageOptions::SignedCharacter
+ : LanguageTwoPageOptions::UnsignedCharacter;
+ floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp"))
+ ? LanguageTwoPageOptions::RelaxedSemantic
+ : LanguageTwoPageOptions::StrictSemantic;
+ enableMultibyteSupport = flags.contains(
+ QLatin1String("--enable_multibytes"));
+ }
+
+ PlainCharacter plainCharacter = SignedCharacter;
+ FloatingPointSemantic floatingPointSemantic = StrictSemantic;
+ int enableMultibyteSupport = 0;
+};
+
+// Optimizations page options.
+
+struct OptimizationsPageOptions final
+{
+ // Optimizations level radio-buttons with
+ // combo-box on "level" widget.
+ enum Strategy {
+ StrategyBalanced,
+ StrategySize,
+ StrategySpeed
+ };
+
+ enum Level {
+ LevelNone,
+ LevelLow,
+ LevelMedium,
+ LevelHigh
+ };
+
+ enum LevelSlave {
+ LevelSlave0,
+ LevelSlave1,
+ LevelSlave2,
+ LevelSlave3
+ };
+
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString optimization = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("optimization"));
+ if (optimization == QLatin1String("none")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategyBalanced;
+ optimizationLevel = OptimizationsPageOptions::LevelNone;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0;
+ } else if (optimization == QLatin1String("fast")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySpeed;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ } else if (optimization == QLatin1String("small")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySize;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ }
+
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ enableCommonSubexpressionElimination = !flags.contains(
+ QLatin1String("--no_cse"));
+ enableFunctionInlining = !flags.contains(QLatin1String("--no_inline"));
+ enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion"));
+ enableCrossCall = !flags.contains(QLatin1String("--no_cross_call"));
+ enableVariableClustering = !flags.contains(
+ QLatin1String("--no_clustering"));
+ enableTypeBasedAliasAnalysis = !flags.contains(
+ QLatin1String("--no_tbaa"));
+ enableForceCrossCall = flags.contains(
+ QLatin1String("--do_cross_call"));
+ }
+
+ Strategy optimizationStrategy = StrategyBalanced;
+ Level optimizationLevel = LevelNone;
+ LevelSlave optimizationLevelSlave = LevelSlave0;
+ // Six bit-field flags on "enabled optimizations" widget.
+ int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination.
+ int enableFunctionInlining = 0; // Function inlining.
+ int enableCodeMotion = 0; // Code motion.
+ int enableCrossCall = 0; // Cross call optimization.
+ int enableVariableClustering = 0; // Variable clustering.
+ int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis.
+ // Force cross-call optimization.
+ int enableForceCrossCall = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const QString &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ warningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int warningsAsErrors = 0;
+};
+
+// Code page options.
+
+struct CodePageOptions final
+{
+ explicit CodePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ placeConstantsInRam = flags.contains(QLatin1String("-y"));
+ placeInitializiersInFlash = flags.contains(
+ QLatin1String("--initializiers_in_flash"));
+ forceVariablesGeneration = flags.contains(
+ QLatin1String("--root_variables"));
+ useIccA90CallingConvention = flags.contains(
+ QLatin1String("--version1_calls"));
+ lockRegistersCount = IarewUtils::flagValue(
+ flags, QStringLiteral("--lock_regs")).toInt();
+ }
+
+ int placeConstantsInRam = 0;
+ int placeInitializiersInFlash = 0;
+ int forceVariablesGeneration = 0;
+ int useIccA90CallingConvention = 0;
+ int lockRegistersCount = 0;
+};
+
+} // namespace
+
+// AvrCompilerSettingsGroup
+
+AvrCompilerSettingsGroup::AvrCompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("ICCAVR"));
+ setArchiveVersion(kCompilerArchiveVersion);
+ setDataVersion(kCompilerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildOutputPage(qbsProduct);
+ buildLanguageOnePage(qbsProduct);
+ buildLanguageTwoPage(qbsProduct);
+ buildOptimizationsPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+ buildCodePage(qbsProduct);
+}
+
+void AvrCompilerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'CCDebugInfo' item (Generate debug info).
+ addOptionsGroup(QByteArrayLiteral("CCDebugInfo"),
+ {}, {opts.debugInfo});
+ // Add 'CCNoErrorMsg' item (No error messages in output files).
+ addOptionsGroup(QByteArrayLiteral("CCNoErrorMsg"),
+ {}, {opts.disableErrorMessages});
+ // Add 'CCOverrideModuleTypeDefault' item
+ // (Override default module type).
+ addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"),
+ {}, {1});
+ // Add 'CCRadioModuleType' item (Module type: program/library).
+ addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"),
+ {}, {opts.moduleType});
+}
+
+void AvrCompilerSettingsGroup::buildLanguageOnePage(
+ const ProductData &qbsProduct)
+{
+ const LanguageOnePageOptions opts(qbsProduct);
+ // Add 'IccLang' item with 'auto-extension based'
+ // value (Language: C/C++/Auto).
+ addOptionsGroup(QByteArrayLiteral("IccLang"),
+ {}, {opts.languageExtension});
+ // Add 'IccCDialect' item (C dialect: c89/99/11).
+ addOptionsGroup(QByteArrayLiteral("IccCDialect"),
+ {}, {opts.cLanguageDialect});
+ // Add 'IccCppDialect' item (C++ dialect: embedded/extended).
+ addOptionsGroup(QByteArrayLiteral("IccCppDialect"),
+ {}, {opts.cxxLanguageDialect});
+ // Add 'CCExt' item (Language conformance: IAR/relaxed/strict).
+ addOptionsGroup(QByteArrayLiteral("CCExt"),
+ {}, {opts.languageConformance});
+ // Add 'IccAllowVLA' item (Allow VLA).
+ addOptionsGroup(QByteArrayLiteral("IccAllowVLA"),
+ {}, {opts.allowVla});
+ // Add 'IccCppInlineSemantics' item (C++ inline semantics).
+ addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"),
+ {}, {opts.useCppInlineSemantics});
+ // Add 'CCRequirePrototypes' item (Require prototypes).
+ addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"),
+ {}, {opts.requirePrototypes});
+ // Add 'IccStaticDestr' item (Destroy static objects).
+ addOptionsGroup(QByteArrayLiteral("IccStaticDestr"),
+ {}, {opts.destroyStaticObjects});
+}
+
+void AvrCompilerSettingsGroup::buildLanguageTwoPage(
+ const ProductData &qbsProduct)
+{
+ const LanguageTwoPageOptions opts(qbsProduct);
+ // Add 'CCCharIs' item (Plain char is: signed/unsigned).
+ addOptionsGroup(QByteArrayLiteral("CCCharIs"),
+ {}, {opts.plainCharacter});
+ // Add 'IccFloatSemantics' item (Floatic-point
+ // semantics: strict/relaxed conformance).
+ addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"),
+ {}, {opts.floatingPointSemantic});
+ // Add 'CCMultibyteSupport' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"),
+ {}, {opts.enableMultibyteSupport});
+}
+
+void AvrCompilerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ const OptimizationsPageOptions opts(qbsProduct);
+ // Add 'CCOptStrategy', 'CCOptLevel' and
+ // 'CCOptLevelSlave' items (Level).
+ addOptionsGroup(QByteArrayLiteral("CCOptStrategy"),
+ {}, {opts.optimizationStrategy});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevel"),
+ {}, {opts.optimizationLevel});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"),
+ {}, {opts.optimizationLevelSlave});
+ // Add 'CCAllowList' item
+ // (Enabled optimizations: 6 check boxes).
+ const QString bitflags = QStringLiteral("%1%2%3%4%5%6")
+ .arg(opts.enableCommonSubexpressionElimination)
+ .arg(opts.enableFunctionInlining)
+ .arg(opts.enableCodeMotion)
+ .arg(opts.enableCrossCall)
+ .arg(opts.enableVariableClustering)
+ .arg(opts.enableTypeBasedAliasAnalysis);
+ addOptionsGroup(QByteArrayLiteral("CCAllowList"),
+ {}, {bitflags});
+ // Add 'CCOptForceCrossCall' item
+ // (Always do cross call optimization).
+ addOptionsGroup(QByteArrayLiteral("CCOptForceCrossCall"),
+ {}, {opts.enableForceCrossCall});
+}
+
+void AvrCompilerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'CCDefines' item (Defines symbols).
+ addOptionsGroup(QByteArrayLiteral("CCDefines"),
+ {}, opts.defineSymbols);
+ // Add 'newCCIncludePaths' item
+ // (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("newCCIncludePaths"),
+ {}, opts.includePaths);
+}
+
+void AvrCompilerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'CCWarnAsError' item (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("CCWarnAsError"),
+ {}, {opts.warningsAsErrors});
+}
+
+void AvrCompilerSettingsGroup::buildCodePage(
+ const ProductData &qbsProduct)
+{
+ const CodePageOptions opts(qbsProduct);
+ // Add 'CCConstInRAM' item (Place string literals
+ // and constants in initialized RAM).
+ addOptionsGroup(QByteArrayLiteral("CCConstInRAM"),
+ {}, {opts.placeConstantsInRam});
+ // Add 'CCInitInFlash' item (Place aggregate
+ // initializiers in flash memory).
+ addOptionsGroup(QByteArrayLiteral("CCInitInFlash"),
+ {}, {opts.placeInitializiersInFlash});
+ // Add 'CCForceVariables' item (Force generation of
+ // all global and static variables).
+ addOptionsGroup(QByteArrayLiteral("CCForceVariables"),
+ {}, {opts.forceVariablesGeneration});
+ // Add 'CCOldCallConv' item (Use ICCA90 1.x
+ // calling convention).
+ addOptionsGroup(QByteArrayLiteral("CCOldCallConv"),
+ {}, {opts.useIccA90CallingConvention});
+ // Add 'CCLockRegs' item (Number of registers to
+ // lock for global variables).
+ addOptionsGroup(QByteArrayLiteral("CCLockRegs"),
+ {}, {opts.lockRegistersCount});
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h
new file mode 100644
index 000000000..2d8c53b84
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H
+#define QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrCompilerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit AvrCompilerSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildLanguageOnePage(const ProductData &qbsProduct);
+ void buildLanguageTwoPage(const ProductData &qbsProduct);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildCodePage(const ProductData &qbsProduct);
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp
new file mode 100644
index 000000000..ff2f303c5
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp
@@ -0,0 +1,774 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrgeneralsettingsgroup_v7.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+constexpr int kGeneralArchiveVersion = 12;
+constexpr int kGeneralDataVersion = 10;
+
+namespace {
+
+struct TargetMcuEntry final
+{
+ QByteArray targetName;
+ QByteArray targetFlag;
+};
+
+// Dictionary of known AVR MCU's and its compiler options.
+static const TargetMcuEntry mcusDict[] = {
+ {"AT43USB320A", "at43usb320a"},
+ {"AT43USB325", "at43usb325"},
+ {"AT43USB326", "at43usb326"},
+ {"AT43USB351M", "at43usb351m"},
+ {"AT43USB353M", "at43usb353m"},
+ {"AT43USB355", "at43usb355"},
+ {"AT76C712", "at76c712"},
+ {"AT76C713", "at76c713"},
+ {"AT86RF401", "at86rf401"},
+ {"AT90CAN128", "can128"},
+ {"AT90CAN32", "can32"},
+ {"AT90CAN64", "can64"},
+ {"AT90PWM1", "pwm1"},
+ {"AT90PWM161", "pwm161"},
+ {"AT90PWM2", "pwm2"},
+ {"AT90PWM216", "pwm216"},
+ {"AT90PWM2B", "pwm2b"},
+ {"AT90PWM3", "pwm3"},
+ {"AT90PWM316", "pwm316"},
+ {"AT90PWM3B", "pwm3b"},
+ {"AT90PWM81", "pwm81"},
+ {"AT90S1200", "1200"},
+ {"AT90S2313", "2313"},
+ {"AT90S2323", "2323"},
+ {"AT90S2333", "2333"},
+ {"AT90S2343", "2343"},
+ {"AT90S4414", "4414"},
+ {"AT90S4433", "4433"},
+ {"AT90S4434", "4434"},
+ {"AT90S8515", "8515"},
+ {"AT90S8534", "8534"},
+ {"AT90S8535", "8535"},
+ {"AT90SCR050", "scr050"},
+ {"AT90SCR075", "scr075"},
+ {"AT90SCR100", "scr100"},
+ {"AT90SCR200", "scr200"},
+ {"AT90SCR400", "scr400"},
+ {"AT90USB128", "usb128"},
+ {"AT90USB1286", "usb1286"},
+ {"AT90USB1287", "usb1287"},
+ {"AT90USB162", "usb162"},
+ {"AT90USB64", "usb64"},
+ {"AT90USB646", "usb646"},
+ {"AT90USB647", "usb647"},
+ {"AT90USB82", "usb82"},
+ {"AT94Kxx", "at94k"},
+ {"ATA5272", "ata5272"},
+ {"ATA5505", "ata5505"},
+ {"ATA5700M322", "ata5700m322"},
+ {"ATA5702M322", "ata5702m322"},
+ {"ATA5781", "ata5781"},
+ {"ATA5782", "ata5782"},
+ {"ATA5783", "ata5783"},
+ {"ATA5785", "ata5785"},
+ {"ATA5787", "ata5787"},
+ {"ATA5790", "ata5790"},
+ {"ATA5790N", "ata5790n"},
+ {"ATA5795", "ata5795"},
+ {"ATA5830", "ata5830"},
+ {"ATA5831", "ata5831"},
+ {"ATA5832", "ata5832"},
+ {"ATA5833", "ata5833"},
+ {"ATA5835", "ata5835"},
+ {"ATA6285", "ata6285"},
+ {"ATA6286", "ata6286"},
+ {"ATA6289", "ata6289"},
+ {"ATA8210", "ata8210"},
+ {"ATA8215", "ata8215"},
+ {"ATA8510", "ata8510"},
+ {"ATA8515", "ata8515"},
+ {"ATmX224E", "mx224e"},
+ {"ATmXT112SL", "mxt112sl"},
+ {"ATmXT224", "mxt224"},
+ {"ATmXT224E", "mxt224e"},
+ {"ATmXT336S", "mxt336s"},
+ {"ATmXT540S", "mxt540s"},
+ {"ATmXT540S_RevA", "mxt540s_reva"},
+ {"ATmXTS200", "mxts200"},
+ {"ATmXTS220", "mxts220"},
+ {"ATmXTS220E", "mxts220e"},
+ {"ATmega007", "m007"},
+ {"ATmega103", "m103"},
+ {"ATmega128", "m128"},
+ {"ATmega1280", "m1280"},
+ {"ATmega1281", "m1281"},
+ {"ATmega1284", "m1284"},
+ {"ATmega1284P", "m1284p"},
+ {"ATmega1284RFR2", "m1284rfr2"},
+ {"ATmega128A", "m128a"},
+ {"ATmega128RFA1", "m128rfa1"},
+ {"ATmega128RFA2", "m128rfa2"},
+ {"ATmega128RFR2", "m128rfr2"},
+ {"ATmega16", "m16"},
+ {"ATmega1608", "m1608"},
+ {"ATmega1609", "m1609"},
+ {"ATmega161", "m161"},
+ {"ATmega162", "m162"},
+ {"ATmega163", "m163"},
+ {"ATmega164", "m164"},
+ {"ATmega164A", "m164a"},
+ {"ATmega164P", "m164p"},
+ {"ATmega164PA", "m164pa"},
+ {"ATmega165", "m165"},
+ {"ATmega165A", "m165a"},
+ {"ATmega165P", "m165p"},
+ {"ATmega165PA", "m165pa"},
+ {"ATmega168", "m168"},
+ {"ATmega168A", "m168a"},
+ {"ATmega168P", "m168p"},
+ {"ATmega168PA", "m168pa"},
+ {"ATmega168PB", "m168pb"},
+ {"ATmega169", "m169"},
+ {"ATmega169A", "m169a"},
+ {"ATmega169P", "m169p"},
+ {"ATmega169PA", "m169pa"},
+ {"ATmega16A", "m16a"},
+ {"ATmega16HVA", "m16hva"},
+ {"ATmega16HVA2", "m16hva2"},
+ {"ATmega16HVB", "m16hvb"},
+ {"ATmega16M1", "m16m1"},
+ {"ATmega16U2", "m16u2"},
+ {"ATmega16U4", "m16u4"},
+ {"ATmega2560", "m2560"},
+ {"ATmega2561", "m2561"},
+ {"ATmega2564RFR2", "m2564rfr2"},
+ {"ATmega256RFA2", "m256rfa2"},
+ {"ATmega256RFR2", "m256rfr2"},
+ {"ATmega26HVG", "m26hvg"},
+ {"ATmega32", "m32"},
+ {"ATmega3208", "m3208"},
+ {"ATmega3209", "m3209"},
+ {"ATmega323", "m323"},
+ {"ATmega324", "m324"},
+ {"ATmega324A", "m324a"},
+ {"ATmega324P", "m324p"},
+ {"ATmega324PA", "m324pa"},
+ {"ATmega324PB", "m324pb"},
+ {"ATmega325", "m325"},
+ {"ATmega3250", "m3250"},
+ {"ATmega3250A", "m3250a"},
+ {"ATmega3250P", "m3250p"},
+ {"ATmega3250PA", "m3250pa"},
+ {"ATmega325A", "m325a"},
+ {"ATmega325P", "m325p"},
+ {"ATmega325PA", "m325pa"},
+ {"ATmega328", "m328"},
+ {"ATmega328P", "m328p"},
+ {"ATmega328PB", "m328pb"},
+ {"ATmega329", "m329"},
+ {"ATmega3290", "m3290"},
+ {"ATmega3290A", "m3290a"},
+ {"ATmega3290P", "m3290p"},
+ {"ATmega3290PA", "m3290pa"},
+ {"ATmega329A", "m329a"},
+ {"ATmega329P", "m329p"},
+ {"ATmega329PA", "m329pa"},
+ {"ATmega32A", "m32a"},
+ {"ATmega32C1", "m32c1"},
+ {"ATmega32HVB", "m32hvb"},
+ {"ATmega32M1", "m32m1"},
+ {"ATmega32U2", "m32u2"},
+ {"ATmega32U4", "m32u4"},
+ {"ATmega32U6", "m32u6"},
+ {"ATmega406", "m406"},
+ {"ATmega48", "m48"},
+ {"ATmega4808", "m4808"},
+ {"ATmega4809", "m4809"},
+ {"ATmega48A", "m48a"},
+ {"ATmega48HVF", "m48hvf"},
+ {"ATmega48P", "m48p"},
+ {"ATmega48PA", "m48pa"},
+ {"ATmega48PB", "m48pb"},
+ {"ATmega4HVD", "m4hvd"},
+ {"ATmega603", "m603"},
+ {"ATmega64", "m64"},
+ {"ATmega640", "m640"},
+ {"ATmega644", "m644"},
+ {"ATmega644A", "m644a"},
+ {"ATmega644P", "m644p"},
+ {"ATmega644PA", "m644pa"},
+ {"ATmega644RFR2", "m644rfr2"},
+ {"ATmega645", "m645"},
+ {"ATmega6450", "m6450"},
+ {"ATmega6450A", "m6450a"},
+ {"ATmega6450P", "m6450p"},
+ {"ATmega645A", "m645a"},
+ {"ATmega645P", "m645p"},
+ {"ATmega649", "m649"},
+ {"ATmega6490", "m6490"},
+ {"ATmega6490A", "m6490a"},
+ {"ATmega6490P", "m6490p"},
+ {"ATmega649A", "m649a"},
+ {"ATmega649P", "m649p"},
+ {"ATmega64A", "m64a"},
+ {"ATmega64C1", "m64c1"},
+ {"ATmega64HVE", "m256rfa2"},
+ {"ATmega64HVE", "m64hve"},
+ {"ATmega64HVE2", "m64hve2"},
+ {"ATmega64M1", "m64m1"},
+ {"ATmega64RFA2", "m64rfa2"},
+ {"ATmega64RFR2", "m64rfr2"},
+ {"ATmega8", "m8"},
+ {"ATmega808", "m808"},
+ {"ATmega809", "m809"},
+ {"ATmega83", "m83"},
+ {"ATmega8515", "m8515"},
+ {"ATmega8535", "m8535"},
+ {"ATmega88", "m88"},
+ {"ATmega88A", "m88a"},
+ {"ATmega88P", "m88p"},
+ {"ATmega88PA", "m88pa"},
+ {"ATmega88PB", "m88pb"},
+ {"ATmega8A", "m8a"},
+ {"ATmega8HVA", "m8hva"},
+ {"ATmega8HVD", "m8hvd"},
+ {"ATmega8U2", "m8u2"},
+ {"ATtiny10", "tiny10"},
+ {"ATtiny102", "tiny102"},
+ {"ATtiny104", "tiny104"},
+ {"ATtiny11", "tiny11"},
+ {"ATtiny12", "tiny12"},
+ {"ATtiny13", "tiny13"},
+ {"ATtiny13A", "tiny13a"},
+ {"ATtiny15", "tiny15"},
+ {"ATtiny1604", "tiny1604"},
+ {"ATtiny1606", "tiny1606"},
+ {"ATtiny1607", "tiny1607"},
+ {"ATtiny1614", "tiny1614"},
+ {"ATtiny1616", "tiny1616"},
+ {"ATtiny1617", "tiny1617"},
+ {"ATtiny1634", "tiny1634"},
+ {"ATtiny167", "tiny167"},
+ {"ATtiny20", "tiny20"},
+ {"ATtiny202", "tiny202"},
+ {"ATtiny204", "tiny204"},
+ {"ATtiny212", "tiny212"},
+ {"ATtiny214", "tiny214"},
+ {"ATtiny22", "tiny22"},
+ {"ATtiny2313", "tiny2313"},
+ {"ATtiny2313A", "tiny2313a"},
+ {"ATtiny23U", "tiny23u"},
+ {"ATtiny24", "tiny24"},
+ {"ATtiny24A", "tiny24a"},
+ {"ATtiny25", "tiny25"},
+ {"ATtiny26", "tiny26"},
+ {"ATtiny261", "tiny261"},
+ {"ATtiny261A", "tiny261a"},
+ {"ATtiny28", "tiny28"},
+ {"ATtiny3214", "tiny3214"},
+ {"ATtiny3216", "tiny3216"},
+ {"ATtiny3217", "tiny3217"},
+ {"ATtiny4", "tiny4"},
+ {"ATtiny40", "tiny40"},
+ {"ATtiny402", "tiny402"},
+ {"ATtiny404", "tiny404"},
+ {"ATtiny406", "tiny406"},
+ {"ATtiny412", "tiny412"},
+ {"ATtiny414", "tiny414"},
+ {"ATtiny416", "tiny416"},
+ {"ATtiny417", "tiny417"},
+ {"ATtiny4313", "tiny4313"},
+ {"ATtiny43U", "tiny43u"},
+ {"ATtiny44", "tiny44"},
+ {"ATtiny441", "tiny441"},
+ {"ATtiny44A", "tiny44a"},
+ {"ATtiny45", "tiny45"},
+ {"ATtiny461", "tiny461"},
+ {"ATtiny461A", "tiny461a"},
+ {"ATtiny474", "tiny474"},
+ {"ATtiny48", "tiny48"},
+ {"ATtiny5", "tiny5"},
+ {"ATtiny80", "tiny80"},
+ {"ATtiny804", "tiny804"},
+ {"ATtiny806", "tiny806"},
+ {"ATtiny807", "tiny807"},
+ {"ATtiny80_pre_2015", "tiny80_pre_2015"},
+ {"ATtiny814", "tiny814"},
+ {"ATtiny816", "tiny816"},
+ {"ATtiny817", "tiny817"},
+ {"ATtiny828", "tiny828"},
+ {"ATtiny84", "tiny84"},
+ {"ATtiny840", "tiny840"},
+ {"ATtiny841", "tiny841"},
+ {"ATtiny84A", "tiny84a"},
+ {"ATtiny85", "tiny85"},
+ {"ATtiny861", "tiny861"},
+ {"ATtiny861A", "tiny861a"},
+ {"ATtiny87", "tiny87"},
+ {"ATtiny88", "tiny88"},
+ {"ATtiny9", "tiny9"},
+ {"ATxmega128A1", "xm128a1"},
+ {"ATxmega128A1U", "xm128a1u"},
+ {"ATxmega128A3", "xm128a3"},
+ {"ATxmega128A3U", "xm128a3u"},
+ {"ATxmega128A4", "xm128a4"},
+ {"ATxmega128A4U", "xm128a4u"},
+ {"ATxmega128B1", "xm128b1"},
+ {"ATxmega128B3", "xm128b3"},
+ {"ATxmega128C3", "xm128c3"},
+ {"ATxmega128D3", "xm128d3"},
+ {"ATxmega128D4", "xm128d4"},
+ {"ATxmega16A4", "xm16a4"},
+ {"ATxmega16A4U", "xm16a4u"},
+ {"ATxmega16C4", "xm16c4"},
+ {"ATxmega16D4", "xm16d4"},
+ {"ATxmega16E5", "xm16e5"},
+ {"ATxmega192A1", "xm192a1"},
+ {"ATxmega192A3", "xm192a3"},
+ {"ATxmega192A3U", "xm192a3u"},
+ {"ATxmega192C3", "xm192c3"},
+ {"ATxmega192D3", "xm192d3"},
+ {"ATxmega256A1", "xm256a1"},
+ {"ATxmega256A3", "xm256a3"},
+ {"ATxmega256A3B", "xm256a3b"},
+ {"ATxmega256A3BU", "xm256a3bu"},
+ {"ATxmega256A3U", "xm256a3u"},
+ {"ATxmega256B1", "xm256b1"},
+ {"ATxmega256C3", "xm256c3"},
+ {"ATxmega256D3", "xm256d3"},
+ {"ATxmega32A4", "xm32a4"},
+ {"ATxmega32A4U", "xm32a4u"},
+ {"ATxmega32C3", "xm32c3"},
+ {"ATxmega32C4", "xm32c4"},
+ {"ATxmega32D3", "xm32d3"},
+ {"ATxmega32D4", "xm32d4"},
+ {"ATxmega32D4P", "xm32d4p"},
+ {"ATxmega32E5", "xm32e5"},
+ {"ATxmega32X1", "xm32x1"},
+ {"ATxmega384A1", "xm384a1"},
+ {"ATxmega384C3", "xm384c3"},
+ {"ATxmega384D3", "xm384d3"},
+ {"ATxmega64A1", "xm64a1"},
+ {"ATxmega64A1U", "xm64a1u"},
+ {"ATxmega64A3", "xm64a3"},
+ {"ATxmega64A3U", "xm64a3u"},
+ {"ATxmega64A4", "xm64a4"},
+ {"ATxmega64A4U", "xm64a4u"},
+ {"ATxmega64B1", "xm64b1"},
+ {"ATxmega64B3", "xm64b3"},
+ {"ATxmega64C3", "xm64c3"},
+ {"ATxmega64D3", "xm64d3"},
+ {"ATxmega64D4", "xm64d4"},
+ {"ATxmega8E5", "xm8e5"},
+ {"M3000", "m3000"},
+ {"MaxBSE", "maxbse"},
+};
+
+// Target page options.
+
+struct TargetPageOptions final
+{
+ enum MemoryModel {
+ TinyModel,
+ SmallModel,
+ LargeModel,
+ HugeModel
+ };
+
+ explicit TargetPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags")});
+ // Detect target MCU record.
+ const QString mcuValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--cpu")).toLower();
+ targetMcu = mcuStringFromFlagValue(mcuValue);
+ // Detect target memory model.
+ const QString modelValue = IarewUtils::flagValue(
+ flags, QStringLiteral("-m"));
+ if (modelValue == QLatin1Char('t'))
+ memoryModel = TargetPageOptions::TinyModel;
+ else if (modelValue == QLatin1Char('s'))
+ memoryModel = TargetPageOptions::SmallModel;
+ else if (modelValue == QLatin1Char('l'))
+ memoryModel = TargetPageOptions::LargeModel;
+ else if (modelValue == QLatin1Char('h'))
+ memoryModel = TargetPageOptions::HugeModel;
+ // Detect target EEPROM util size.
+ eepromUtilSize = IarewUtils::flagValue(
+ flags, QStringLiteral("--eeprom_size")).toInt();
+ }
+
+ static QString mcuStringFromFlagValue(const QString &mcuValue)
+ {
+ const auto targetBegin = std::cbegin(mcusDict);
+ const auto targetEnd = std::cend(mcusDict);
+ const auto targetIt = std::find_if(targetBegin, targetEnd,
+ [mcuValue](
+ const TargetMcuEntry &entry) {
+ return entry.targetFlag == mcuValue.toLatin1();
+ });
+ if (targetIt != targetEnd) {
+ return QStringLiteral("%1\t%2")
+ .arg(QString::fromLatin1(targetIt->targetFlag),
+ QString::fromLatin1(targetIt->targetName));
+ }
+ return {};
+ }
+
+ QString targetMcu;
+ MemoryModel memoryModel = TinyModel;
+ int eepromUtilSize = 0;
+};
+
+// System page options.
+
+struct SystemPageOptions final
+{
+ explicit SystemPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverLinkerFlags"),
+ QStringLiteral("defines")});
+ cstackSize = IarewUtils::flagValue(
+ flags, QStringLiteral("_..X_CSTACK_SIZE")).toInt();
+ rstackSize = IarewUtils::flagValue(
+ flags, QStringLiteral("_..X_RSTACK_SIZE")).toInt();
+ }
+
+ int cstackSize = 0;
+ int rstackSize = 0;
+};
+
+// Library options page options.
+
+struct LibraryOptionsPageOptions final
+{
+ enum PrintfFormatter {
+ PrintfAutoFormatter = 0,
+ PrintfFullFormatter = 1,
+ PrintfFullNoMultibytesFormatter = 2,
+ PrintfLargeFormatter = 3,
+ PrintfLargeNoMultibytesFormatter = 4,
+ PrintfSmallFormatter = 6,
+ PrintfSmallNoMultibytesFormatter = 7,
+ PrintfTinyFormatter = 8
+ };
+
+ enum ScanfFormatter {
+ ScanfAutoFormatter = 0,
+ ScanfFullFormatter = 1,
+ ScanfFullNoMultibytesFormatter = 2,
+ ScanfLargeFormatter = 3,
+ ScanfLargeNoMultibytesFormatter = 4,
+ ScanfSmallFormatter = 6,
+ ScanfSmallNoMultibytesFormatter = 7
+ };
+
+ explicit LibraryOptionsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ for (const QString &flag : flags) {
+ if (flag.endsWith(QLatin1String("_printf"), Qt::CaseInsensitive)) {
+ const QString prop = flag.split(QLatin1Char('=')).at(0).toLower();
+ if (prop == QLatin1String("-e_printffull"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfFullFormatter;
+ else if (prop == QLatin1String("-e_printffullnomb"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfFullNoMultibytesFormatter;
+ else if (prop == QLatin1String("-e_printflarge"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter;
+ else if (prop == QLatin1String("-e_printflargenomb"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfLargeNoMultibytesFormatter;
+ else if (prop == QLatin1String("-e_printfsmall"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter;
+ else if (prop == QLatin1String("-e_printfsmallnomb"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfSmallNoMultibytesFormatter;
+ else if (prop == QLatin1String("-printftiny"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfTinyFormatter;
+ } else if (flag.endsWith(QLatin1String("_scanf"), Qt::CaseInsensitive)) {
+ const QString prop = flag.split(QLatin1Char('=')).at(0).toLower();
+ if (prop == QLatin1String("-e_scanffull"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfFullFormatter;
+ else if (prop == QLatin1String("-e_scanffullnomb"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfFullNoMultibytesFormatter;
+ else if (prop == QLatin1String("-e_scanflarge"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter;
+ else if (prop == QLatin1String("-e_scanflargenomb"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfLargeNoMultibytesFormatter;
+ else if (prop == QLatin1String("-e_scanfsmall"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfSmallFormatter;
+ else if (prop == QLatin1String("-e_scanfsmallnomb"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfSmallNoMultibytesFormatter;
+ }
+ }
+ }
+
+ PrintfFormatter printfFormatter = PrintfAutoFormatter;
+ ScanfFormatter scanfFormatter = ScanfAutoFormatter;
+};
+
+// Library configuration page options.
+
+struct LibraryConfigPageOptions final
+{
+ enum RuntimeLibrary {
+ NoLibrary,
+ NormalDlibLibrary,
+ FullDlibLibrary,
+ CustomDlibLibrary,
+ ClibLibrary,
+ CustomClibLibrary,
+ ThirdPartyLibrary
+ };
+
+ explicit LibraryConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ const QStringList libraryPaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ const auto libraryBegin = libraryPaths.cbegin();
+ const auto libraryEnd = libraryPaths.cend();
+
+ if (flags.contains(QLatin1String("--dlib"))) {
+ const QString dlibToolkitPath =
+ IarewUtils::dlibToolkitRootPath(qbsProduct);
+ const QFileInfo configInfo(IarewUtils::flagValue(
+ flags,
+ QStringLiteral("--dlib_config")));
+ const QString configFilePath = configInfo.absoluteFilePath();
+ if (configFilePath.startsWith(dlibToolkitPath,
+ Qt::CaseInsensitive)) {
+ if (configFilePath.endsWith(QLatin1String("-n.h"),
+ Qt::CaseInsensitive)) {
+ libraryType = LibraryConfigPageOptions::NormalDlibLibrary;
+ } else if (configFilePath.endsWith(QLatin1String("-f.h"),
+ Qt::CaseInsensitive)) {
+ libraryType = LibraryConfigPageOptions::FullDlibLibrary;
+ } else {
+ libraryType = LibraryConfigPageOptions::CustomDlibLibrary;
+ }
+
+ configPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, configFilePath);
+
+ // Find dlib library inside of IAR toolkit directory.
+ const auto libraryIt = std::find_if(libraryBegin, libraryEnd,
+ [dlibToolkitPath](
+ const QString &libraryPath) {
+ return libraryPath.startsWith(dlibToolkitPath);
+ });
+ if (libraryIt != libraryEnd) {
+ // This means that dlib library is 'standard' (placed inside
+ // of IAR toolkit directory).
+ libraryPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, *libraryIt);
+ }
+ } else {
+ // This means that dlib library is 'custom'
+ // (but we don't know its path).
+ libraryType = LibraryConfigPageOptions::CustomDlibLibrary;
+ configPath = IarewUtils::projectRelativeFilePath(
+ baseDirectory, configFilePath);
+ }
+ } else if (flags.contains(QLatin1String("--clib"))) {
+ const QString clibToolkitPath =
+ IarewUtils::clibToolkitRootPath(qbsProduct);
+ // Find clib library inside of IAR toolkit directory.
+ const auto libraryIt = std::find_if(libraryBegin, libraryEnd,
+ [clibToolkitPath](
+ const QString &libraryPath) {
+ return libraryPath.startsWith(clibToolkitPath);
+ });
+ if (libraryIt != libraryEnd) {
+ // This means that clib library is 'standard' (placed inside
+ // of IAR toolkit directory).
+ libraryType = LibraryConfigPageOptions::ClibLibrary;
+ libraryPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, *libraryIt);
+ } else {
+ // This means that clib library is 'custom'
+ // (but we don't know its path).
+ libraryType = LibraryConfigPageOptions::CustomClibLibrary;
+ }
+ } else {
+ libraryType = LibraryConfigPageOptions::NoLibrary;
+ }
+ }
+
+ RuntimeLibrary libraryType = NoLibrary;
+ QString configPath;
+ QString libraryPath;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ binaryType = IarewUtils::outputBinaryType(qbsProduct);
+ binaryDirectory = gen::utils::binaryOutputDirectory(
+ baseDirectory, qbsProduct);
+ objectDirectory = gen::utils::objectsOutputDirectory(
+ baseDirectory, qbsProduct);
+ listingDirectory = gen::utils::listingOutputDirectory(
+ baseDirectory, qbsProduct);
+ }
+
+ IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType;
+ QString binaryDirectory;
+ QString objectDirectory;
+ QString listingDirectory;
+};
+
+} // namespace
+
+// AvrGeneralSettingsGroup
+
+AvrGeneralSettingsGroup::AvrGeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("General"));
+ setArchiveVersion(kGeneralArchiveVersion);
+ setDataVersion(kGeneralDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildTargetPage(qbsProduct);
+ buildSystemPage(qbsProduct);
+ buildLibraryOptionsPage(qbsProduct);
+ buildLibraryConfigPage(buildRootDirectory, qbsProduct);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void AvrGeneralSettingsGroup::buildTargetPage(
+ const ProductData &qbsProduct)
+{
+ const TargetPageOptions opts(qbsProduct);
+ // Add 'GenDeviceSelectMenu' item
+ // (Processor configuration chooser).
+ addOptionsGroup(QByteArrayLiteral("GenDeviceSelectMenu"),
+ {}, {opts.targetMcu});
+ // Add 'Variant Memory' item
+ // (Memory model: tiny/small/large/huge).
+ addOptionsGroup(QByteArrayLiteral("Variant Memory"),
+ {}, {opts.memoryModel});
+ // Add 'GGEepromUtilSize' item
+ // (Utilize inbuilt EEPROM size, in bytes).
+ addOptionsGroup(QByteArrayLiteral("GGEepromUtilSize"),
+ {}, {opts.eepromUtilSize});
+}
+
+void AvrGeneralSettingsGroup::buildSystemPage(
+ const ProductData &qbsProduct)
+{
+ const SystemPageOptions opts (qbsProduct);
+ // Add 'SCCStackSize' item (Data stack
+ // - CSTACK size in bytes).
+ addOptionsGroup(QByteArrayLiteral("SCCStackSize"),
+ {}, {opts.cstackSize});
+ // Add 'SCRStackSize' item (Return address stack
+ // - RSTACK depth in bytes).
+ addOptionsGroup(QByteArrayLiteral("SCRStackSize"),
+ {}, {opts.rstackSize});
+}
+
+void AvrGeneralSettingsGroup::buildLibraryOptionsPage(
+ const ProductData &qbsProduct)
+{
+ const LibraryOptionsPageOptions opts(qbsProduct);
+ // Add 'Output variant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("Output variant"),
+ {}, {opts.printfFormatter});
+ // Add 'Input variant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("Input variant"),
+ {}, {opts.scanfFormatter});
+}
+
+void AvrGeneralSettingsGroup::buildLibraryConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const LibraryConfigPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items
+ // (Link with runtime: none/dlib/clib/etc).
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"),
+ {}, {opts.libraryType});
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"),
+ {}, {opts.libraryType});
+ // Add 'RTConfigPath' item (Runtime configuration file).
+ addOptionsGroup(QByteArrayLiteral("RTConfigPath"),
+ {}, {opts.configPath});
+ // Add 'RTLibraryPath' item (Runtime library file).
+ addOptionsGroup(QByteArrayLiteral("RTLibraryPath"),
+ {}, {opts.libraryPath});
+}
+
+void AvrGeneralSettingsGroup::buildOutputPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GOutputBinary' item (Output file: executable/library).
+ addOptionsGroup(QByteArrayLiteral("GOutputBinary"),
+ {}, {opts.binaryType});
+ // Add 'ExePath' item (Executable/binaries output directory).
+ addOptionsGroup(QByteArrayLiteral("ExePath"),
+ {}, {opts.binaryDirectory});
+ // Add 'ObjPath' item (Object files output directory).
+ addOptionsGroup(QByteArrayLiteral("ObjPath"),
+ {}, {opts.objectDirectory});
+ // Add 'ListPath' item (List files output directory).
+ addOptionsGroup(QByteArrayLiteral("ListPath"),
+ {}, {opts.listingDirectory});
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h
new file mode 100644
index 000000000..5411eeae8
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H
+#define QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrGeneralSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit AvrGeneralSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildTargetPage(const ProductData &qbsProduct);
+ void buildSystemPage(const ProductData &qbsProduct);
+ void buildLibraryOptionsPage(const ProductData &qbsProduct);
+ void buildLibraryConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp
new file mode 100644
index 000000000..9b86a860e
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "avrlinkersettingsgroup_v7.h"
+
+#include "../../iarewutils.h"
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+constexpr int kLinkerArchiveVersion = 3;
+constexpr int kLinkerDataVersion = 16;
+
+namespace {
+
+// Config page options.
+
+struct ConfigPageOptions final
+{
+ explicit ConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+
+ entryPoint = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("entryPoint"));
+
+ // Enumerate all product linker config files
+ // (which are set trough 'linkerscript' tag).
+ const auto qbsGroups = qbsProduct.groups();
+ for (const auto &qbsGroup : qbsGroups) {
+ const auto qbsArtifacts = qbsGroup.sourceArtifacts();
+ for (const auto &qbsArtifact : qbsArtifacts) {
+ const auto qbsTags = qbsArtifact.fileTags();
+ if (!qbsTags.contains(QLatin1String("linkerscript")))
+ continue;
+ const QString fullConfigPath = qbsArtifact.filePath();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ configFilePaths.push_back(path);
+ }
+ }
+ }
+
+ // Enumerate all product linker config files
+ // (which are set trough '-f' option).
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ const QVariantList configPathValues = IarewUtils::flagValues(
+ flags, QStringLiteral("-f"));
+ for (const QVariant &configPathValue : configPathValues) {
+ const QString fullConfigPath = configPathValue.toString();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ }
+ }
+
+ // Add libraries search paths.
+ const QStringList libraryPaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("libraryPaths")});
+ for (const QString &libraryPath : libraryPaths) {
+ const QFileInfo libraryPathInfo(libraryPath);
+ const QString fullLibrarySearchPath =
+ libraryPathInfo.absoluteFilePath();
+ if (fullLibrarySearchPath.startsWith(toolkitPath,
+ Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ }
+ }
+
+ // Add static libraries paths.
+ const QStringList staticLibrariesProps =
+ gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ for (const QString &staticLibrary : staticLibrariesProps) {
+ const QFileInfo staticLibraryInfo(staticLibrary);
+ if (staticLibraryInfo.isAbsolute()) {
+ const QString fullStaticLibraryPath =
+ staticLibraryInfo.absoluteFilePath();
+ if (fullStaticLibraryPath.startsWith(toolkitPath,
+ Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ }
+ } else {
+ staticLibraries.push_back(staticLibrary);
+ }
+ }
+
+ // Add static libraries from product dependencies.
+ for (const ProductData &qbsProductDep : qbsProductDeps) {
+ const QString depBinaryPath = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory,
+ qbsProductDep);
+ staticLibraries.push_back(depBinaryPath);
+ }
+ }
+
+ QVariantList configFilePaths;
+ QVariantList librarySearchPaths;
+ QVariantList staticLibraries;
+ QString entryPoint;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ outputFile = gen::utils::targetBinary(qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+// List page options.
+
+struct ListPageOptions final
+{
+ enum ListingAction {
+ NoListing,
+ GenerateListing
+ };
+
+ explicit ListPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ generateMap = gen::utils::cppBooleanModuleProperty(
+ qbsProps, QStringLiteral("generateMapFile"))
+ ? ListPageOptions::GenerateListing
+ : ListPageOptions::NoListing;
+ }
+
+ ListingAction generateMap = NoListing;
+};
+
+// Define page options.
+
+struct DefinePageOptions final
+{
+ explicit DefinePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ // Enumerate all linker defines.
+ for (const QString &flag : flags) {
+ if (!flag.startsWith(QLatin1String("-D")))
+ continue;
+ const auto symbol = flag.mid(2);
+ // Ignore system-defined macroses.
+ if (symbol.startsWith(QLatin1String("_..X_HEAP_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_TINY_HEAP_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_NEAR_HEAP_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_FAR_HEAP_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_HUGE_HEAP_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_CSTACK_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_FLASH_CODE_END"))
+ || symbol.startsWith(QLatin1String("_..X_FLASH_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_CSTACK_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_CSTACK_END"))
+ || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_RSTACK_END"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_ROM_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_ROM_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_NV_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_EXT_NV_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_SRAM_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_SRAM_SIZE"))
+ || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE"))
+ || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE"))
+ ) {
+ continue;
+ }
+ defineSymbols.push_back(symbol);
+ }
+ }
+
+ QVariantList defineSymbols;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString warningLevel = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ suppressAllWarnings = (warningLevel == QLatin1String("none"));
+ }
+
+ int suppressAllWarnings = 0;
+};
+
+} // namespace
+
+// AvrLinkerSettingsGroup
+
+AvrLinkerSettingsGroup::AvrLinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ setName(QByteArrayLiteral("XLINK"));
+ setArchiveVersion(kLinkerArchiveVersion);
+ setDataVersion(kLinkerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildConfigPage(buildRootDirectory, qbsProduct, qbsProductDeps);
+ buildOutputPage(qbsProduct);
+ buildListPage(qbsProduct);
+ buildDefinePage(qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+
+ // Should be called as latest stage!
+ buildExtraOptionsPage(qbsProduct);
+}
+
+void AvrLinkerSettingsGroup::buildConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ ConfigPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps);
+
+ if (opts.configFilePaths.count() > 0) {
+ // Note: IAR IDE does not allow to specify a multiple config files,
+ // although the IAR linker support it. So, we use followig 'trick':
+ // we take a first config file and to add it as usual to required items;
+ // and then an other remainders we forward to the "Extra options page".
+ const QVariant configPath = opts.configFilePaths.takeFirst();
+ // Add 'XclOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("XclOverride"),
+ {}, {1});
+ // Add 'XclFile' item (Linke configuration file).
+ addOptionsGroup(QByteArrayLiteral("XclFile"),
+ {}, {configPath});
+
+ // Add remainder configuration files to the "Extra options page".
+ if (!opts.configFilePaths.isEmpty()) {
+ for (QVariant &configPath : opts.configFilePaths)
+ configPath = QLatin1String("-f ") + configPath.toString();
+
+ m_extraOptions << opts.configFilePaths;
+ }
+ }
+
+ if (opts.staticLibraries.count() > 0)
+ m_extraOptions << opts.staticLibraries;
+
+ if (!opts.entryPoint.isEmpty()) {
+ // Add 'xcProgramEntryLabel' item (Entry symbol).
+ addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"),
+ {}, {opts.entryPoint});
+ // Add 'xcOverrideProgramEntryLabel' item
+ // (Override default program entry).
+ addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"),
+ {}, {1});
+ // Add 'xcProgramEntryLabelSelect' item.
+ addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"),
+ {}, {0});
+ }
+
+ // Add 'XIncludes' item (Libraries search paths).
+ addOptionsGroup(QByteArrayLiteral("XIncludes"),
+ {}, opts.librarySearchPaths);
+}
+
+void AvrLinkerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'XOutOverride' item (Override default output file).
+ addOptionsGroup(QByteArrayLiteral("XOutOverride"),
+ {}, {1});
+ // Add 'OutputFile' item (Output file name).
+ addOptionsGroup(QByteArrayLiteral("OutputFile"),
+ {}, {opts.outputFile});
+}
+
+void AvrLinkerSettingsGroup::buildListPage(
+ const ProductData &qbsProduct)
+{
+ const ListPageOptions opts(qbsProduct);
+ // Add 'XList' item (Generate linker listing).
+ addOptionsGroup(QByteArrayLiteral("XList"),
+ {}, {opts.generateMap});
+}
+
+void AvrLinkerSettingsGroup::buildDefinePage(
+ const ProductData &qbsProduct)
+{
+ const DefinePageOptions opts(qbsProduct);
+ // Add 'XDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("XDefines"),
+ {}, opts.defineSymbols);
+}
+
+void AvrLinkerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'SuppressAllWarn' item (Suppress all warnings).
+ addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"),
+ {}, {opts.suppressAllWarnings});
+}
+
+void AvrLinkerSettingsGroup::buildExtraOptionsPage(const ProductData &qbsProduct)
+{
+ Q_UNUSED(qbsProduct)
+
+ if (!m_extraOptions.isEmpty()) {
+ // Add 'XExtraOptionsCheck' (Use command line options).
+ addOptionsGroup(QByteArrayLiteral("XExtraOptionsCheck"),
+ {}, {1});
+ // Add 'XExtraOptions' item (Command line options).
+ addOptionsGroup(QByteArrayLiteral("XExtraOptions"),
+ {}, m_extraOptions);
+ }
+}
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h
new file mode 100644
index 000000000..5427937b7
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H
+#define QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace avr {
+namespace v7 {
+
+class AvrLinkerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit AvrLinkerSettingsGroup(const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildListPage(const ProductData &qbsProduct);
+ void buildDefinePage(const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildExtraOptionsPage(const ProductData &qbsProduct);
+
+ QVariantList m_extraOptions;
+};
+
+} // namespace v7
+} // namespace avr
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp
new file mode 100644
index 000000000..36978bd15
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51archiversettingsgroup_v10.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+constexpr int kArchiverArchiveVersion = 2;
+constexpr int kArchiverDataVersion = 1;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ outputFile = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory, qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+} // namespace
+
+// Mcs51ArchiverSettingsGroup
+
+Mcs51ArchiverSettingsGroup::Mcs51ArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("XAR"));
+ setArchiveVersion(kArchiverArchiveVersion);
+ setDataVersion(kArchiverDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void Mcs51ArchiverSettingsGroup::buildOutputPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'XAROverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("XAROverride"),
+ {}, {1});
+ // Add 'XAROutput2' item (Output filename).
+ addOptionsGroup(QByteArrayLiteral("XAROutput2"),
+ {}, {opts.outputFile});
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h
new file mode 100644
index 000000000..21c66433d
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H
+#define QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51ArchiverSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Mcs51ArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp
new file mode 100644
index 000000000..5f72f20e4
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51assemblersettingsgroup_v10.h"
+
+//#include "../../iarewproperty.h"
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+constexpr int kAssemblerArchiveVersion = 2;
+constexpr int kAssemblerDataVersion = 6;
+
+namespace {
+
+// Language page options.
+
+struct LanguagePageOptions final
+{
+ enum MacroQuoteCharacter {
+ AngleBracketsQuote,
+ RoundBracketsQuote,
+ SquareBracketsQuote,
+ FigureBracketsQuote
+ };
+
+ explicit LanguagePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("assemblerFlags")});
+ enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+"));
+ enableMultibyteSupport = flags.contains(QLatin1String("-n"));
+
+ if (flags.contains(QLatin1String("-M<>")))
+ macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote;
+ else if (flags.contains(QLatin1String("-M()")))
+ macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote;
+ else if (flags.contains(QLatin1String("-M[]")))
+ macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote;
+ else if (flags.contains(QLatin1String("-M{}")))
+ macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote;
+ }
+
+ MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote;
+ int enableSymbolsCaseSensitive = 0;
+ int enableMultibyteSupport = 0;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const auto &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString warningLevel = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ if (warningLevel == QLatin1String("all")) {
+ enableWarnings = 0;
+ enableAllWarnings = 0;
+ } else if (warningLevel == QLatin1String("none")) {
+ enableWarnings = 1;
+ enableAllWarnings = 0;
+ } else {
+ enableWarnings = 0;
+ enableAllWarnings = 1;
+ }
+ }
+
+ int enableWarnings = 0;
+ int enableAllWarnings = 0;
+};
+
+} // namespace
+
+// Mcs51AssemblerSettingsGroup
+
+Mcs51AssemblerSettingsGroup::Mcs51AssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("A8051"));
+ setArchiveVersion(kAssemblerArchiveVersion);
+ setDataVersion(kAssemblerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildLanguagePage(qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void Mcs51AssemblerSettingsGroup::buildLanguagePage(
+ const ProductData &qbsProduct)
+{
+ const LanguagePageOptions opts(qbsProduct);
+ // Add 'ACaseSensitivity' item (User symbols are case sensitive).
+ addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"),
+ {}, {opts.enableSymbolsCaseSensitive});
+ // Add 'Asm multibyte support' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("Asm multibyte support"),
+ {}, {opts.enableMultibyteSupport});
+ // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>).
+ addOptionsGroup(QByteArrayLiteral("MacroChars"),
+ {0}, {!opts.macroQuoteCharacter});
+}
+
+void Mcs51AssemblerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'Debug' item (Generate debug information).
+ addOptionsGroup(QByteArrayLiteral("Debug"),
+ {}, {opts.debugInfo});
+}
+
+void Mcs51AssemblerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'ADefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("ADefines"),
+ {}, opts.defineSymbols);
+ // Add 'Include directories' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("Include directories"),
+ {}, opts.includePaths);
+}
+
+void Mcs51AssemblerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'AWarnEnable' item (Enable/disable warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnEnable"),
+ {}, {opts.enableWarnings});
+ // Add 'AWarnWhat' item (Enable/disable all warnings).
+ addOptionsGroup(QByteArrayLiteral("AWarnWhat"),
+ {}, {opts.enableAllWarnings});
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h
new file mode 100644
index 000000000..bb9f4b613
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H
+#define QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51AssemblerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Mcs51AssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildLanguagePage(const ProductData &qbsProduct);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp
new file mode 100644
index 000000000..ba86bc54d
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51archiversettingsgroup_v10.h"
+#include "mcs51assemblersettingsgroup_v10.h"
+#include "mcs51buildconfigurationgroup_v10.h"
+#include "mcs51compilersettingsgroup_v10.h"
+#include "mcs51generalsettingsgroup_v10.h"
+#include "mcs51linkersettingsgroup_v10.h"
+
+#include "../../iarewtoolchainpropertygroup.h"
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+Mcs51BuildConfigurationGroup::Mcs51BuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup("configuration")
+{
+ // Append configuration name item.
+ const QString cfgName = gen::utils::buildConfigurationName(qbsProject);
+ appendProperty("name", cfgName);
+
+ // Apend toolchain name group item.
+ appendChild<IarewToolchainPropertyGroup>("8051");
+
+ // Append debug info item.
+ const int debugBuild = gen::utils::debugInformation(qbsProduct);
+ appendProperty("debug", debugBuild);
+
+ // Append settings group items.
+ appendChild<Mcs51ArchiverSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Mcs51AssemblerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Mcs51CompilerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Mcs51GeneralSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Mcs51LinkerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+}
+
+bool Mcs51BuildConfigurationGroupFactory::canCreate(
+ gen::utils::Architecture arch,
+ const Version &version) const
+{
+ return arch == gen::utils::Architecture::Mcs51
+ && version.majorVersion() == 10;
+}
+
+std::unique_ptr<gen::xml::PropertyGroup>
+Mcs51BuildConfigurationGroupFactory::create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const
+{
+ const auto group = new Mcs51BuildConfigurationGroup(
+ qbsProject, qbsProduct, qbsProductDeps);
+ return std::unique_ptr<Mcs51BuildConfigurationGroup>(group);
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h
new file mode 100644
index 000000000..edd16d5d7
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H
+#define QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51BuildConfigurationGroup final
+ : public gen::xml::PropertyGroup
+{
+private:
+ explicit Mcs51BuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+ friend class Mcs51BuildConfigurationGroupFactory;
+};
+
+class Mcs51BuildConfigurationGroupFactory final
+ : public gen::xml::PropertyGroupFactory
+{
+public:
+ bool canCreate(gen::utils::Architecture arch,
+ const Version &version) const final;
+
+ std::unique_ptr<gen::xml::PropertyGroup> create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const final;
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp
new file mode 100644
index 000000000..bda3d090b
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp
@@ -0,0 +1,476 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51compilersettingsgroup_v10.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+constexpr int kCompilerArchiveVersion = 7;
+constexpr int kCompilerDataVersion = 12;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ enum ModuleType {
+ ProgramModule,
+ LibraryModule
+ };
+
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ moduleType = flags.contains(QLatin1String("--library_module"))
+ ? OutputPageOptions::LibraryModule
+ : OutputPageOptions::ProgramModule;
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+ ModuleType moduleType = ProgramModule;
+};
+
+// Language one page options.
+
+struct LanguageOnePageOptions final
+{
+ enum LanguageExtension {
+ CLanguageExtension,
+ CxxLanguageExtension,
+ AutoLanguageExtension
+ };
+
+ enum CLanguageDialect {
+ C89LanguageDialect,
+ C99LanguageDialect
+ };
+
+ enum CxxLanguageDialect {
+ EmbeddedCPlusPlus,
+ ExtendedEmbeddedCPlusPlus
+ };
+
+ enum LanguageConformance {
+ AllowIarExtension,
+ RelaxedStandard,
+ StrictStandard
+ };
+
+ explicit LanguageOnePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ // File extension based by default.
+ languageExtension = LanguageOnePageOptions::AutoLanguageExtension;
+ // C language dialect.
+ const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("cLanguageVersion")});
+ cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89"))
+ ? LanguageOnePageOptions::C89LanguageDialect
+ : LanguageOnePageOptions::C99LanguageDialect;
+ // C++ language dialect.
+ if (flags.contains(QLatin1String("--ec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus;
+ else if (flags.contains(QLatin1String("--eec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus;
+ // Language conformance.
+ if (flags.contains(QLatin1String("-e")))
+ languageConformance = LanguageOnePageOptions::AllowIarExtension;
+ else if (flags.contains(QLatin1String("--strict")))
+ languageConformance = LanguageOnePageOptions::StrictStandard;
+ else
+ languageConformance = LanguageOnePageOptions::RelaxedStandard;
+
+ allowVla = flags.contains(QLatin1String("--vla"));
+ useCppInlineSemantics = flags.contains(
+ QLatin1String("--use_c++_inline"));
+ requirePrototypes = flags.contains(
+ QLatin1String("--require_prototypes"));
+ destroyStaticObjects = !flags.contains(
+ QLatin1String("--no_static_destruction"));
+ }
+
+ LanguageExtension languageExtension = AutoLanguageExtension;
+ CLanguageDialect cLanguageDialect = C89LanguageDialect;
+ CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus;
+ LanguageConformance languageConformance = AllowIarExtension;
+ int allowVla = 0;
+ int useCppInlineSemantics = 0;
+ int requirePrototypes = 0;
+ int destroyStaticObjects = 0;
+};
+
+// Language two page options.
+
+struct LanguageTwoPageOptions final
+{
+ enum PlainCharacter {
+ SignedCharacter,
+ UnsignedCharacter
+ };
+
+ enum FloatingPointSemantic {
+ StrictSemantic,
+ RelaxedSemantic
+ };
+
+ explicit LanguageTwoPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ plainCharacter = flags.contains(
+ QLatin1String("--char_is_signed"))
+ ? LanguageTwoPageOptions::SignedCharacter
+ : LanguageTwoPageOptions::UnsignedCharacter;
+ floatingPointSemantic = flags.contains(
+ QLatin1String("--relaxed_fp"))
+ ? LanguageTwoPageOptions::RelaxedSemantic
+ : LanguageTwoPageOptions::StrictSemantic;
+ enableMultibyteSupport = flags.contains(
+ QLatin1String("--enable_multibytes"));
+ }
+
+ PlainCharacter plainCharacter = SignedCharacter;
+ FloatingPointSemantic floatingPointSemantic = StrictSemantic;
+ int enableMultibyteSupport = 0;
+};
+
+// Optimizations page options.
+
+struct OptimizationsPageOptions final
+{
+ // Optimizations level radio-buttons with combo-box
+ // on "level" widget.
+ enum Strategy {
+ StrategyBalanced,
+ StrategySize,
+ StrategySpeed
+ };
+
+ enum Level {
+ LevelNone,
+ LevelLow,
+ LevelMedium,
+ LevelHigh
+ };
+
+ enum LevelSlave {
+ LevelSlave0,
+ LevelSlave1,
+ LevelSlave2,
+ LevelSlave3
+ };
+
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString optimization = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("optimization"));
+ if (optimization == QLatin1String("none")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategyBalanced;
+ optimizationLevel = OptimizationsPageOptions::LevelNone;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0;
+ } else if (optimization == QLatin1String("fast")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySpeed;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ } else if (optimization == QLatin1String("small")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySize;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ }
+
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ enableCommonSubexpressionElimination = !flags.contains(
+ QLatin1String("--no_cse"));
+ enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll"));
+ enableFunctionInlining = !flags.contains(QLatin1String("--no_inline"));
+ enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion"));
+ enableTypeBasedAliasAnalysis = !flags.contains(
+ QLatin1String("--no_tbaa"));
+ enableCrossCall = !flags.contains(QLatin1String("--no_cross_call"));
+ disableRegisterBanks = flags.contains(
+ QLatin1String("--disable_register_banks"));
+
+ disableSizeConstrains = flags.contains(
+ QLatin1String("--no_size_constraints"));
+ }
+
+ Strategy optimizationStrategy = StrategyBalanced;
+ Level optimizationLevel = LevelNone;
+ LevelSlave optimizationLevelSlave = LevelSlave0;
+ // Seven bit-field flags on "enabled transformations" widget.
+ int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination.
+ int enableLoopUnroll = 0; // Loop unrolling.
+ int enableFunctionInlining = 0; // Function inlining.
+ int enableCodeMotion = 0; // Code motion.
+ int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis.
+ int enableCrossCall = 0; // Cross call optimization.
+ int disableRegisterBanks = 0; // Disabled register banks.
+ int disableSizeConstrains = 0; // No size constraints.
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ // TODO: Need to exclude the pre-defined maroses which are handled
+ // in 'General Options'.
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath(qbsProduct);
+ for (const QString &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ // Exclude dlib config includes because it already handled in
+ // 'General Options->Library configuration page'.
+ if (includeFilePath.startsWith(dlibToolkitPath))
+ continue;
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ warningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int warningsAsErrors = 0;
+};
+
+// Code page options.
+
+struct CodePageOptions final
+{
+ explicit CodePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ paddingForRomMonitorBreakpoints = flags.contains(
+ QLatin1String("--rom_mon_bp_padding"));
+ excludeUbrofMessagesInOutput = flags.contains(
+ QLatin1String("--no_ubrof_messages"));
+ }
+
+ int paddingForRomMonitorBreakpoints = 0;
+ int excludeUbrofMessagesInOutput = 0;
+};
+
+} // namespace
+
+// Mcs51CompilerSettingsGroup
+
+Mcs51CompilerSettingsGroup::Mcs51CompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("ICC8051"));
+ setArchiveVersion(kCompilerArchiveVersion);
+ setDataVersion(kCompilerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildOutputPage(qbsProduct);
+ buildLanguageOnePage(qbsProduct);
+ buildLanguageTwoPage(qbsProduct);
+ buildOptimizationsPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void Mcs51CompilerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'CCDebugInfo' item (Generate debug info).
+ addOptionsGroup(QByteArrayLiteral("CCDebugInfo"),
+ {}, {opts.debugInfo});
+ // Add 'CCOverrideModuleTypeDefault' item
+ // (Override default module type).
+ addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"),
+ {}, {1});
+ // Add 'CCRadioModuleType' item (Module type: program/library).
+ addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"),
+ {}, {opts.moduleType});
+}
+
+void Mcs51CompilerSettingsGroup::buildLanguageOnePage(
+ const ProductData &qbsProduct)
+{
+ const LanguageOnePageOptions opts(qbsProduct);
+ // Add 'IccLang' item with 'auto-extension based'
+ // value (Language: C/C++/Auto).
+ addOptionsGroup(QByteArrayLiteral("IccLang"),
+ {}, {opts.languageExtension});
+ // Add 'IccCDialect' item (C dialect: c89/99/11).
+ addOptionsGroup(QByteArrayLiteral("IccCDialect"),
+ {}, {opts.cLanguageDialect});
+ // Add 'IccCppDialect' item (C++ dialect: embedded/extended).
+ addOptionsGroup(QByteArrayLiteral("IccCppDialect"),
+ {}, {opts.cxxLanguageDialect});
+ // Add 'CCExt' item (Language conformance: IAR/relaxed/strict).
+ addOptionsGroup(QByteArrayLiteral("LangConform"),
+ {}, {opts.languageConformance});
+ // Add 'IccAllowVLA' item (Allow VLA).
+ addOptionsGroup(QByteArrayLiteral("IccAllowVLA"),
+ {}, {opts.allowVla});
+ // Add 'IccCppInlineSemantics' item (C++ inline semantics).
+ addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"),
+ {}, {opts.useCppInlineSemantics});
+ // Add 'CCRequirePrototypes' item (Require prototypes).
+ addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"),
+ {}, {opts.requirePrototypes});
+ // Add 'IccStaticDestr' item (Destroy static objects).
+ addOptionsGroup(QByteArrayLiteral("IccStaticDestr"),
+ {}, {opts.destroyStaticObjects});
+}
+
+void Mcs51CompilerSettingsGroup::buildLanguageTwoPage(
+ const ProductData &qbsProduct)
+{
+ const LanguageTwoPageOptions opts(qbsProduct);
+ // Add 'CharIs' item (Plain char is: signed/unsigned).
+ addOptionsGroup(QByteArrayLiteral("CharIs"),
+ {}, {opts.plainCharacter});
+ // Add 'IccFloatSemantics' item
+ // (Floatic-point semantics: strict/relaxed conformance).
+ addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"),
+ {}, {opts.floatingPointSemantic});
+ // Add 'CCMultibyteSupport' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"),
+ {}, {opts.enableMultibyteSupport});
+}
+
+void Mcs51CompilerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ const OptimizationsPageOptions opts(qbsProduct);
+ // Add 'CCOptStrategy', 'CCOptLevel' and
+ // 'CCOptLevelSlave' items (Level).
+ addOptionsGroup(QByteArrayLiteral("CCOptStrategy"),
+ {}, {opts.optimizationStrategy});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevel"),
+ {}, {opts.optimizationLevel});
+ addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"),
+ {}, {opts.optimizationLevelSlave});
+ // Add 'CCAllowList2' item (Enabled transformations: 7 check boxes).
+ const QString transformations = QStringLiteral("%1%2%3%4%5%6%7")
+ .arg(opts.enableCommonSubexpressionElimination)
+ .arg(opts.enableLoopUnroll)
+ .arg(opts.enableFunctionInlining)
+ .arg(opts.enableCodeMotion)
+ .arg(opts.enableTypeBasedAliasAnalysis)
+ .arg(opts.enableCrossCall)
+ .arg(opts.disableRegisterBanks);
+ addOptionsGroup(QByteArrayLiteral("CCAllowList2"),
+ {}, {transformations});
+ // Add 'NoSizeConstraints' item (No size constraints).
+ addOptionsGroup(QByteArrayLiteral("NoSizeConstraints"),
+ {}, {opts.disableSizeConstrains});
+}
+
+void Mcs51CompilerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'CCDefines' item (Defines symbols).
+ addOptionsGroup(QByteArrayLiteral("CCDefines"),
+ {}, opts.defineSymbols);
+ // Add 'CCIncludePath2' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("CCIncludePath2"),
+ {}, opts.includePaths);
+}
+
+void Mcs51CompilerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"),
+ {}, {opts.warningsAsErrors});
+}
+
+void Mcs51CompilerSettingsGroup::buildCodePage(
+ const ProductData &qbsProduct)
+{
+ const CodePageOptions opts(qbsProduct);
+ // Add 'RomMonBpPadding' item (Padding for ROM-monitor breakpoints).
+ addOptionsGroup(QByteArrayLiteral("RomMonBpPadding"),
+ {}, {opts.paddingForRomMonitorBreakpoints});
+ // Add 'NoUBROFMessages' item (No UBROF messages in output files).
+ addOptionsGroup(QByteArrayLiteral("NoUBROFMessages"),
+ {}, {opts.excludeUbrofMessagesInOutput});
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h
new file mode 100644
index 000000000..e68a7628f
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H
+#define QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51CompilerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Mcs51CompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildLanguageOnePage(const ProductData &qbsProduct);
+ void buildLanguageTwoPage(const ProductData &qbsProduct);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildCodePage(const ProductData &qbsProduct);
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp
new file mode 100644
index 000000000..28e051489
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp
@@ -0,0 +1,1014 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51generalsettingsgroup_v10.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+constexpr int kGeneralArchiveVersion = 4;
+constexpr int kGeneralDataVersion = 9;
+
+namespace {
+
+// Target page options.
+
+struct TargetPageOptions final
+{
+ enum CpuCore {
+ CorePlain = 1,
+ CoreExtended1,
+ CoreExtended2
+ };
+
+ enum CodeModel {
+ CodeModelNear = 1,
+ CodeModelBanked,
+ CodeModelFar,
+ CodeModelBankedExtended2
+ };
+
+ enum DataModel {
+ DataModelTiny = 0,
+ DataModelSmall,
+ DataModelLarge,
+ DataModelGeneric,
+ DataModelFarGeneric,
+ DataModelFar
+ };
+
+ enum ConstantsMemoryPlacement {
+ RamMemoryPlace = 0,
+ RomMemoryPlace,
+ CodeMemoryPlace
+ };
+
+ enum CallingConvention {
+ DataOverlayConvention = 0,
+ IDataOverlayConvention,
+ IDataReentrantConvention,
+ PDataReentrantConvention,
+ XDataReentrantConvention,
+ ExtendedStackReentrantConvention
+ };
+
+ explicit TargetPageOptions(const ProductData &qbsProduct)
+ {
+ chipInfoPath = detectChipInfoPath(qbsProduct);
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ // Should be parsed before the 'code_model' and
+ // 'data_model' options, as that options are depends on it.
+ const QString core = IarewUtils::flagValue(
+ flags, QStringLiteral("--core"))
+ .toLower();
+ if (core == QLatin1String("plain")) {
+ cpuCore = TargetPageOptions::CorePlain;
+ } else if (core == QLatin1String("extended1")) {
+ cpuCore = TargetPageOptions::CoreExtended1;
+ } else if (core == QLatin1String("extended2")) {
+ cpuCore = TargetPageOptions::CoreExtended2;
+ } else {
+ // If the core variant is not set, then choose the
+ // default values (see the compiler datasheet for
+ // '--core' option).
+ cpuCore = TargetPageOptions::CorePlain;
+ }
+
+ const QString cm = IarewUtils::flagValue(
+ flags, QStringLiteral("--code_model"))
+ .toLower();
+ if (cm == QLatin1String("near")) {
+ codeModel = TargetPageOptions::CodeModelNear;
+ } else if (cm == QLatin1String("banked")) {
+ codeModel = TargetPageOptions::CodeModelBanked;
+ } else if (cm == QLatin1String("far")) {
+ codeModel = TargetPageOptions::CodeModelFar;
+ } else if (cm == QLatin1String("banked_ext2")) {
+ codeModel = TargetPageOptions::CodeModelBankedExtended2;
+ } else {
+ // If the code model is not set, then choose the
+ // default values (see the compiler datasheet for
+ // '--code_model' option).
+ if (cpuCore == TargetPageOptions::CorePlain)
+ codeModel = TargetPageOptions::CodeModelNear;
+ else if (cpuCore == TargetPageOptions::CoreExtended1)
+ codeModel = TargetPageOptions::CodeModelFar;
+ else if (cpuCore == TargetPageOptions::CoreExtended2)
+ codeModel = TargetPageOptions::CodeModelBankedExtended2;
+ }
+
+ const QString dm = IarewUtils::flagValue(
+ flags, QStringLiteral("--data_model")).toLower();
+ if (dm == QLatin1String("tiny")) {
+ dataModel = TargetPageOptions::DataModelTiny;
+ } else if (dm == QLatin1String("small")) {
+ dataModel = TargetPageOptions::DataModelSmall;
+ } else if (dm == QLatin1String("large")) {
+ dataModel = TargetPageOptions::DataModelLarge;
+ } else if (dm == QLatin1String("generic")) {
+ dataModel = TargetPageOptions::DataModelGeneric;
+ } else if (dm == QLatin1String("far_generic")) {
+ dataModel = TargetPageOptions::DataModelFarGeneric;
+ } else if (dm == QLatin1String("far")) {
+ dataModel = TargetPageOptions::DataModelFar;
+ } else {
+ // If the data model is not set, then choose the
+ // default values (see the compiler datasheet for
+ // '--data_model' option).
+ if (cpuCore == TargetPageOptions::CorePlain)
+ dataModel = TargetPageOptions::DataModelSmall;
+ else if (cpuCore == TargetPageOptions::CoreExtended1)
+ dataModel = TargetPageOptions::DataModelFar;
+ else if (cpuCore == TargetPageOptions::CoreExtended2)
+ dataModel = TargetPageOptions::DataModelLarge;
+ }
+
+ useExtendedStack = flags.contains(QLatin1String("--extended_stack"));
+
+ const int regsCount = IarewUtils::flagValue(
+ flags, QStringLiteral("--nr_virtual_regs"))
+ .toInt();
+ enum { MinVRegsCount = 8, MaxVRegsCount = 32, VRegsOffset = 8 };
+ // The registers index starts with 0: 0 - means 8 registers,
+ // 1 - means 9 registers and etc. Any invalid values we interpret
+ // as a default value in 8 registers.
+ virtualRegisters = (regsCount < MinVRegsCount || regsCount > MaxVRegsCount)
+ ? 0 : (regsCount - VRegsOffset);
+
+ const QString constPlace = IarewUtils::flagValue(
+ flags, QStringLiteral("--place_constants"))
+ .toLower();
+ if (constPlace == QLatin1String("data")) {
+ constPlacement = TargetPageOptions::RamMemoryPlace;
+ } else if (constPlace == QLatin1String("data_rom")) {
+ constPlacement = TargetPageOptions::RomMemoryPlace;
+ } else if (constPlace == QLatin1String("code")) {
+ constPlacement = TargetPageOptions::CodeMemoryPlace;
+ } else {
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--place_constants' option).
+ constPlacement = TargetPageOptions::RamMemoryPlace;
+ }
+
+ const QString cc = IarewUtils::flagValue(
+ flags, QStringLiteral("--calling_convention")).toLower();
+ if (cc == QLatin1String("data_overlay")) {
+ callingConvention = TargetPageOptions::DataOverlayConvention;
+ } else if (cc == QLatin1String("idata_overlay")) {
+ callingConvention = TargetPageOptions::IDataOverlayConvention;
+ } else if (cc == QLatin1String("idata_reentrant")) {
+ callingConvention = TargetPageOptions::IDataReentrantConvention;
+ } else if (cc == QLatin1String("pdata_reentrant")) {
+ callingConvention = TargetPageOptions::PDataReentrantConvention;
+ } else if (cc == QLatin1String("xdata_reentrant")) {
+ callingConvention = TargetPageOptions::XDataReentrantConvention;
+ } else if (cc == QLatin1String("ext_stack_reentrant")) {
+ callingConvention = TargetPageOptions::ExtendedStackReentrantConvention;
+ } else {
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--calling_convention' option).
+ callingConvention = TargetPageOptions::IDataReentrantConvention;
+ }
+ }
+
+ // Trying to indirectly detect and build the chip config path,
+ // which uses to show a device name in "Device information" group box.
+ static QString detectChipInfoPath(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+
+ QVariantList configPaths;
+
+ // Enumerate all product linker config files
+ // (which are set trough '-f' option).
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ configPaths << IarewUtils::flagValues(flags, QStringLiteral("-f"));
+
+ // Enumerate all product linker config files
+ // (which are set trough 'linkerscript' tag).
+ const auto qbsGroups = qbsProduct.groups();
+ for (const auto &qbsGroup : qbsGroups) {
+ const auto qbsArtifacts = qbsGroup.sourceArtifacts();
+ for (const auto &qbsArtifact : qbsArtifacts) {
+ const auto qbsTags = qbsArtifact.fileTags();
+ if (!qbsTags.contains(QLatin1String("linkerscript")))
+ continue;
+ const auto configPath = qbsArtifact.filePath();
+ // Skip duplicates.
+ if (configPaths.contains(configPath))
+ continue;
+ configPaths << qbsArtifact.filePath();
+ }
+ }
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ for (const QVariant &configPath : configPaths) {
+ const QString fullConfigPath = configPath.toString();
+ // We interested only in a config paths shipped inside of a toolkit.
+ if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive))
+ continue;
+ // Extract the chip name from the linker script name.
+ const int underscoreIndex = fullConfigPath.lastIndexOf(QLatin1Char('_'));
+ if (underscoreIndex == -1)
+ continue;
+ const int dotIndex = fullConfigPath.lastIndexOf(QLatin1Char('.'));
+ if (dotIndex == -1)
+ continue;
+ if (dotIndex <= underscoreIndex)
+ continue;
+ const QString chipName = fullConfigPath.mid(
+ underscoreIndex + 1,
+ dotIndex - underscoreIndex - 1);
+ // Construct full chip info path.
+ const QFileInfo fullChipInfoPath(QFileInfo(fullConfigPath).absolutePath()
+ + QLatin1Char('/') + chipName
+ + QLatin1String(".i51"));
+ if (fullChipInfoPath.exists())
+ return fullChipInfoPath.absoluteFilePath();
+ }
+
+ return {};
+ }
+
+ QString chipInfoPath;
+ CpuCore cpuCore = CorePlain;
+ CodeModel codeModel = CodeModelNear;
+ DataModel dataModel = DataModelTiny;
+ int useExtendedStack = 0;
+ int virtualRegisters = 0;
+ ConstantsMemoryPlacement constPlacement = RamMemoryPlace;
+ CallingConvention callingConvention = DataOverlayConvention;
+};
+
+// System page options.
+
+struct StackHeapPageOptions final
+{
+ explicit StackHeapPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList defineSymbols = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+ const QStringList linkerFlags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverLinkerFlags")});
+
+ idataStack = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_IDATA_STACK_SIZE"));
+ if (idataStack.isEmpty())
+ idataStack = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_IDATA_STACK_SIZE"));
+ if (idataStack.isEmpty())
+ idataStack = QLatin1String("0x40"); // Default IDATA stack size.
+ pdataStack = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_PDATA_STACK_SIZE"));
+ if (pdataStack.isEmpty())
+ pdataStack = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_PDATA_STACK_SIZE"));
+ if (pdataStack.isEmpty())
+ pdataStack = QLatin1String("0x80"); // Default PDATA stack size.
+ xdataStack = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_XDATA_STACK_SIZE"));
+ if (xdataStack.isEmpty())
+ xdataStack = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_XDATA_STACK_SIZE"));
+ if (xdataStack.isEmpty())
+ xdataStack = QLatin1String("0xEFF"); // Default XDATA stack size.
+ extendedStack = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_EXTENDED_STACK_SIZE"));
+ if (extendedStack.isEmpty())
+ extendedStack = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_EXTENDED_STACK_SIZE"));
+ if (extendedStack.isEmpty())
+ extendedStack = QLatin1String("0x3FF"); // Default EXTENDED stack size.
+
+ xdataHeap = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_XDATA_HEAP_SIZE"));
+ if (xdataHeap.isEmpty())
+ xdataHeap = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_XDATA_HEAP_SIZE"));
+ if (xdataHeap.isEmpty())
+ xdataHeap = QLatin1String("0xFF"); // Default XDATA heap size.
+ farHeap = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_FAR_HEAP_SIZE"));
+ if (farHeap.isEmpty())
+ farHeap = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_FAR_HEAP_SIZE"));
+ if (farHeap.isEmpty())
+ farHeap = QLatin1String("0xFFF"); // Default FAR heap size.
+ far22Heap = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_FAR22_HEAP_SIZE"));
+ if (far22Heap.isEmpty())
+ far22Heap = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_FAR22_HEAP_SIZE"));
+ if (far22Heap.isEmpty())
+ far22Heap = QLatin1String("0xFFF"); // Default FAR22 heap size.
+ hugeHeap = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_HUGE_HEAP_SIZE"));
+ if (hugeHeap.isEmpty())
+ hugeHeap = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_HUGE_HEAP_SIZE"));
+ if (hugeHeap.isEmpty())
+ hugeHeap = QLatin1String("0xFFF"); // Default HUGE heap size.
+
+ extStackAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?ESP"));
+ if (extStackAddress.isEmpty())
+ extStackAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?ESP"));
+ if (extStackAddress.isEmpty())
+ extStackAddress = QLatin1String("0x9B"); // Default extended stack pointer address.
+ extStackMask = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?ESP_MASK"));
+ if (extStackMask.isEmpty())
+ extStackMask = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?ESP_MASK"));
+ if (extStackMask.isEmpty())
+ extStackMask = QLatin1String("0x03"); // Default extended stack pointer mask.
+ }
+
+ // Stack sizes.
+ QString idataStack;
+ QString pdataStack;
+ QString xdataStack;
+ QString extendedStack;
+ // Heap sizes.
+ QString xdataHeap;
+ QString farHeap;
+ QString far22Heap;
+ QString hugeHeap;
+ // Extended stack.
+ QString extStackAddress;
+ QString extStackMask;
+ int extStackOffset = 0;
+ int extStackStartAddress = 0;
+};
+
+// Data pointer page options.
+
+struct DptrPageOptions final
+{
+ enum DptrSize {
+ Dptr16,
+ Dptr24
+ };
+
+ enum DptrVisibility {
+ DptrShadowed,
+ DptrSeparate
+ };
+
+ enum SwitchMethod {
+ DptrIncludeMethod,
+ DptrMaskMethod
+ };
+
+ explicit DptrPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ const QString core = IarewUtils::flagValue(
+ flags, QStringLiteral("--core"));
+
+ const QString dptr = IarewUtils::flagValue(
+ flags, QStringLiteral("--dptr"));
+ enum ValueIndex { SizeIndex, NumbersIndex,
+ VisibilityIndex, SwitchMethodIndex };
+ const QStringList dptrparts = dptr.split(QLatin1Char(','));
+ for (auto index = 0; index < dptrparts.count(); ++index) {
+ const QString part = dptrparts.at(index).toLower();
+ switch (index) {
+ case SizeIndex:
+ if (part == QLatin1String("16")) {
+ dptrSize = DptrPageOptions::Dptr16;
+ } else if (part == QLatin1String("24")) {
+ dptrSize = DptrPageOptions::Dptr24;
+ } else {
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--dptr' option).
+ if (core == QLatin1String("extended1"))
+ dptrSize = DptrPageOptions::Dptr24;
+ else
+ dptrSize = DptrPageOptions::Dptr16;
+ }
+ break;
+ case NumbersIndex: {
+ const int count = part.toInt();
+ if (count < 1 || count > 8) {
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--dptr' option).
+ if (core == QLatin1String("extended1"))
+ dptrsCountIndex = 1; // 2 DPTR's
+ else
+ dptrsCountIndex = 0; // 1 DPTR's
+ } else {
+ dptrsCountIndex = (count - 1); // DPTR's count - 1
+ }
+ }
+ break;
+ case VisibilityIndex:
+ if (part == QLatin1String("shadowed"))
+ dptrVisibility = DptrPageOptions::DptrShadowed;
+ else if (part == QLatin1String("separate"))
+ dptrVisibility = DptrPageOptions::DptrSeparate;
+ else
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--dptr' option).
+ dptrVisibility = DptrPageOptions::DptrSeparate;
+ break;
+ case SwitchMethodIndex:
+ if (part == QLatin1String("inc")) {
+ dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod;
+ } else if (part.startsWith(QLatin1String("xor"))) {
+ dptrSwitchMethod = DptrPageOptions::DptrMaskMethod;
+ const int firstIndex = part.indexOf(QLatin1Char('('));
+ const int lastIndex = part.indexOf(QLatin1Char(')'));
+ dptrMask = part.mid(firstIndex + 1, part.size() - lastIndex);
+ } else {
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '--dptr' option).
+ if (core == QLatin1String("extended1")) {
+ dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod;
+ } else if (core == QLatin1String("plain")) {
+ dptrSwitchMethod = DptrPageOptions::DptrMaskMethod;
+ dptrMask = QLatin1String("0x01");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ const QStringList defineSymbols = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+ const QStringList linkerFlags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverLinkerFlags")});
+
+ dptrPbank = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?PBANK"));
+ if (dptrPbank.isEmpty())
+ dptrPbank = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?PBANK"));
+ if (dptrPbank.isEmpty())
+ dptrPbank = QLatin1String("0x93"); // Default 8-15 regs address.
+ dptrPbankExt = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?PBANK_EXT"));
+ if (dptrPbankExt.isEmpty())
+ dptrPbankExt = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?PBANK_EXT"));
+
+ dpsAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPS"));
+ if (dpsAddress.isEmpty())
+ dpsAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPS"));
+ dpcAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPC"));
+ if (dpcAddress.isEmpty())
+ dpcAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPC"));
+
+ for (auto index = 0; index < 8; ++index) {
+ if (index == 0) {
+ QString dpxAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPX"));
+ if (dpxAddress.isEmpty())
+ dpxAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPX"));
+ if (!dpxAddress.isEmpty())
+ dpxAddress.prepend(QLatin1String("-D?DPX="));
+ if (!dptrAddresses.contains(dpxAddress))
+ dptrAddresses.push_back(dpxAddress);
+ } else {
+ QString dplAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPL%1").arg(index));
+ if (dplAddress.isEmpty())
+ dplAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPL%1").arg(index));
+ if (!dplAddress.isEmpty())
+ dplAddress.prepend(QStringLiteral("-D?DPL%1=").arg(index));
+ if (!dptrAddresses.contains(dplAddress))
+ dptrAddresses.push_back(dplAddress);
+
+ QString dphAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPH%1").arg(index));
+ if (dphAddress.isEmpty())
+ dphAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPH%1").arg(index));
+ if (!dphAddress.isEmpty())
+ dphAddress.prepend(QStringLiteral("-D?DPH%1=").arg(index));
+ if (!dptrAddresses.contains(dphAddress))
+ dptrAddresses.push_back(dphAddress);
+
+ QString dpxAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?DPX%1").arg(index));
+ if (dpxAddress.isEmpty())
+ dpxAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?DPX%1").arg(index));
+ if (!dpxAddress.isEmpty())
+ dpxAddress.prepend(QStringLiteral("-D?DPX%1=").arg(index));
+ if (!dptrAddresses.contains(dpxAddress))
+ dptrAddresses.push_back(dpxAddress);
+ }
+ }
+ }
+
+ int dptrsCountIndex = 0;
+ DptrSize dptrSize = Dptr16;
+ DptrVisibility dptrVisibility = DptrShadowed;
+ SwitchMethod dptrSwitchMethod = DptrIncludeMethod;
+ QString dptrMask;
+ QString dptrPbank;
+ QString dptrPbankExt;
+ QString dpsAddress;
+ QString dpcAddress;
+ QStringList dptrAddresses;
+};
+
+// Code bank page options.
+
+struct CodeBankPageOptions final
+{
+ explicit CodeBankPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList defineSymbols = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+ const QStringList linkerFlags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverLinkerFlags")});
+
+ banksCount = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_NR_OF_BANKS"));
+ if (banksCount.isEmpty())
+ banksCount = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_NR_OF_BANKS"));
+ if (banksCount.isEmpty())
+ banksCount = QLatin1String("0x03");
+ registerAddress = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?CBANK"));
+ if (registerAddress.isEmpty())
+ registerAddress = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?CBANK"));
+ if (registerAddress.isEmpty())
+ registerAddress = QLatin1String("0xF0");
+ registerMask = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("?CBANK_MASK"));
+ if (registerMask.isEmpty())
+ registerMask = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D?CBANK_MASK"));
+ if (registerMask.isEmpty())
+ registerMask = QLatin1String("0xFF");
+ bankStart = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_CODEBANK_START"));
+ if (bankStart.isEmpty())
+ bankStart = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_CODEBANK_START"));
+ if (bankStart.isEmpty())
+ bankStart = QLatin1String("0x8000");
+ bankEnd = IarewUtils::flagValue(
+ defineSymbols, QStringLiteral("_CODEBANK_END"));
+ if (bankEnd.isEmpty())
+ bankEnd = IarewUtils::flagValue(
+ linkerFlags, QStringLiteral("-D_CODEBANK_END"));
+ if (bankEnd.isEmpty())
+ bankEnd = QLatin1String("0xFFFF");
+ }
+
+ QString banksCount;
+ QString registerAddress;
+ QString registerMask;
+ QString bankStart;
+ QString bankEnd;
+};
+
+// Library options page options.
+
+struct LibraryOptionsPageOptions final
+{
+ enum PrintfFormatter {
+ PrintfAutoFormatter = 0,
+ PrintfLargeFormatter = 3,
+ PrintfMediumFormatter = 5,
+ PrintfSmallFormatter = 6
+ };
+
+ enum ScanfFormatter {
+ ScanfAutoFormatter = 0,
+ ScanfLargeFormatter = 3,
+ ScanfMediumFormatter = 5
+ };
+
+ explicit LibraryOptionsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ for (const QString &flag : flags) {
+ if (flag.endsWith(QLatin1String("_formatted_write"),
+ Qt::CaseInsensitive)) {
+ const QString prop = flag.split(
+ QLatin1Char('=')).at(0).toLower();
+ if (prop == QLatin1String("-e_large_write"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter;
+ else if (prop == QLatin1String("-e_medium_write"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfMediumFormatter;
+ else if (prop == QLatin1String("-e_small_write"))
+ printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter;
+ else
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '_formatted_write' option).
+ printfFormatter = LibraryOptionsPageOptions::PrintfMediumFormatter;
+ } else if (flag.endsWith(QLatin1String("_formatted_read"),
+ Qt::CaseInsensitive)) {
+ const QString prop = flag.split(QLatin1Char('='))
+ .at(0).toLower();
+ if (prop == QLatin1String("-e_large_read"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter;
+ else if (prop == QLatin1String("-e_medium_read"))
+ scanfFormatter = LibraryOptionsPageOptions::ScanfMediumFormatter;
+ else
+ // If this option is not set, then choose the
+ // default value (see the compiler datasheet for
+ // '_formatted_read' option).
+ scanfFormatter = LibraryOptionsPageOptions::ScanfMediumFormatter;
+ }
+ }
+ }
+
+ PrintfFormatter printfFormatter = PrintfAutoFormatter;
+ ScanfFormatter scanfFormatter = ScanfAutoFormatter;
+};
+
+// Library configuration page options.
+
+struct LibraryConfigPageOptions final
+{
+ enum RuntimeLibrary {
+ NoLibrary,
+ NormalDlibLibrary,
+ CustomDlibLibrary,
+ ClibLibrary,
+ CustomClibLibrary
+ };
+
+ explicit LibraryConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ const QStringList libraryPaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ const auto libraryBegin = libraryPaths.cbegin();
+ const auto libraryEnd = libraryPaths.cend();
+
+ const QFileInfo dlibConfigInfo(IarewUtils::flagValue(
+ flags, QStringLiteral("--dlib_config")));
+ const QString dlibConfigFilePath = dlibConfigInfo.absoluteFilePath();
+ if (!dlibConfigFilePath.isEmpty()) {
+ const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath(
+ qbsProduct);
+ if (dlibConfigFilePath.startsWith(dlibToolkitPath,
+ Qt::CaseInsensitive)) {
+ libraryType = LibraryConfigPageOptions::NormalDlibLibrary;
+ configPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, dlibConfigFilePath);
+
+ // Find dlib library inside of IAR toolkit directory.
+ const auto libraryIt = std::find_if(libraryBegin, libraryEnd,
+ [dlibToolkitPath](
+ const QString &libraryPath) {
+ return libraryPath.startsWith(dlibToolkitPath);
+ });
+ if (libraryIt != libraryEnd) {
+ // This means that dlib library is 'standard' (placed inside
+ // of IAR toolkit directory).
+ libraryPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, *libraryIt);
+ }
+ } else {
+ // This means that dlib library is 'custom'
+ // (but we don't know its path).
+ libraryType = LibraryConfigPageOptions::CustomDlibLibrary;
+ configPath = IarewUtils::projectRelativeFilePath(
+ baseDirectory, dlibConfigFilePath);
+ }
+ } else {
+ // Find clib library inside of IAR toolkit directory.
+ const QString clibToolkitPath = IarewUtils::clibToolkitRootPath(
+ qbsProduct);
+ const auto libraryIt = std::find_if(libraryBegin, libraryEnd,
+ [clibToolkitPath](
+ const QString &libraryPath) {
+ return libraryPath.startsWith(clibToolkitPath);
+ });
+ if (libraryIt != libraryEnd) {
+ // This means that clib library is 'standard' (placed inside
+ // of IAR toolkit directory).
+ libraryType = LibraryConfigPageOptions::ClibLibrary;
+ libraryPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, *libraryIt);
+ } else {
+ // This means that no any libraries are used .
+ libraryType = LibraryConfigPageOptions::NoLibrary;
+ }
+ }
+ }
+
+ RuntimeLibrary libraryType = NoLibrary;
+ QString configPath;
+ QString libraryPath;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ binaryType = IarewUtils::outputBinaryType(qbsProduct);
+ binaryDirectory = gen::utils::binaryOutputDirectory(
+ baseDirectory, qbsProduct);
+ objectDirectory = gen::utils::objectsOutputDirectory(
+ baseDirectory, qbsProduct);
+ listingDirectory = gen::utils::listingOutputDirectory(
+ baseDirectory, qbsProduct);
+ }
+
+ IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType;
+ QString binaryDirectory;
+ QString objectDirectory;
+ QString listingDirectory;
+};
+
+} // namespace
+
+// Mcs51GeneralSettingsGroup
+
+Mcs51GeneralSettingsGroup::Mcs51GeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("General"));
+ setArchiveVersion(kGeneralArchiveVersion);
+ setDataVersion(kGeneralDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildTargetPage(qbsProduct);
+ buildStackHeapPage(qbsProduct);
+ buildDataPointerPage(qbsProduct);
+ buildCodeBankPage(qbsProduct);
+ buildLibraryOptionsPage(qbsProduct);
+ buildLibraryConfigPage(buildRootDirectory, qbsProduct);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void Mcs51GeneralSettingsGroup::buildTargetPage(
+ const ProductData &qbsProduct)
+{
+ const TargetPageOptions opts(qbsProduct);
+ // Add 'OGChipConfigPath' item (Device: <chip name>).
+ addOptionsGroup(QByteArrayLiteral("OGChipConfigPath"),
+ {}, {opts.chipInfoPath});
+
+ // Add 'CPU Core' and 'CPU Core Slave' items
+ // (CPU core: plain/extended{1|2}).
+ addOptionsGroup(QByteArrayLiteral("CPU Core"),
+ {}, {opts.cpuCore});
+ addOptionsGroup(QByteArrayLiteral("CPU Core Slave"),
+ {}, {opts.cpuCore});
+ // Add 'Code Memory Model' and 'Code Memory Model slave' items
+ // (Code model: near/banked/far/banked extended).
+ addOptionsGroup(QByteArrayLiteral("Code Memory Model"),
+ {}, {opts.codeModel});
+ addOptionsGroup(QByteArrayLiteral("Code Memory Model slave"),
+ {}, {opts.codeModel});
+ // Add 'Data Memory Model' and 'Data Memory Model slave' items
+ // (Data model: tiny/small/large/generic/far).
+ addOptionsGroup(QByteArrayLiteral("Data Memory Model"),
+ {}, {opts.dataModel});
+ addOptionsGroup(QByteArrayLiteral("Data Memory Model slave"),
+ {}, {opts.dataModel});
+ // Add 'Use extended stack' and 'Use extended stack slave' items
+ // (Use extended stack).
+ addOptionsGroup(QByteArrayLiteral("Use extended stack"),
+ {}, {opts.useExtendedStack});
+ addOptionsGroup(QByteArrayLiteral("Use extended stack slave"),
+ {}, {opts.useExtendedStack});
+ // Add 'Workseg Size' item (Number of virtual registers: 8...32).
+ addOptionsGroup(QByteArrayLiteral("Workseg Size"),
+ {}, {opts.virtualRegisters});
+ // Add 'Constant Placement' item
+ // (Location of constants and strings: ram/rom/code memories).
+ addOptionsGroup(QByteArrayLiteral("Constant Placement"),
+ {}, {opts.constPlacement});
+ // Add 'Calling convention' item (Calling convention).
+ addOptionsGroup(QByteArrayLiteral("Calling convention"),
+ {}, {opts.callingConvention});
+}
+
+void Mcs51GeneralSettingsGroup::buildStackHeapPage(
+ const ProductData &qbsProduct)
+{
+ const StackHeapPageOptions opts(qbsProduct);
+ // Add 'General Idata Stack Size' item (Stack size: IDATA).
+ addOptionsGroup(QByteArrayLiteral("General Idata Stack Size"),
+ {}, {opts.idataStack});
+ // Add 'General Pdata Stack Size' item (Stack size: PDATA).
+ addOptionsGroup(QByteArrayLiteral("General Pdata Stack Size"),
+ {}, {opts.pdataStack});
+ // Add 'General Xdata Stack Size' item (Stack size: XDATA).
+ addOptionsGroup(QByteArrayLiteral("General Xdata Stack Size"),
+ {}, {opts.xdataStack});
+ // Add 'General Ext Stack Size' item (Stack size: Extended).
+ addOptionsGroup(QByteArrayLiteral("General Ext Stack Size"),
+ {}, {opts.extendedStack});
+
+ // Add 'General Xdata Heap Size' item (Heap size: XDATA).
+ addOptionsGroup(QByteArrayLiteral("General Xdata Heap Size"),
+ {}, {opts.xdataHeap});
+ // Add 'General Far Heap Size' item (Heap size: Far).
+ addOptionsGroup(QByteArrayLiteral("General Far Heap Size"),
+ {}, {opts.farHeap});
+ // Add 'General Far22 Heap Size' item (Heap size: Far22).
+ addOptionsGroup(QByteArrayLiteral("General Far22 Heap Size"),
+ {}, {opts.far22Heap});
+ // Add 'General Huge Heap Size' item (Heap size: Huge).
+ addOptionsGroup(QByteArrayLiteral("General Huge Heap Size"),
+ {}, {opts.hugeHeap});
+
+ // Add 'Extended stack address' item
+ // (Extended stack pointer address).
+ addOptionsGroup(QByteArrayLiteral("Extended stack address"),
+ {}, {opts.extStackAddress});
+ // Add 'Extended stack mask' item (Extended stack pointer mask).
+ addOptionsGroup(QByteArrayLiteral("Extended stack mask"),
+ {}, {opts.extStackMask});
+ // Add 'Extended stack is offset' item
+ // (Extended stack pointer is an offset).
+ addOptionsGroup(QByteArrayLiteral("Extended stack is offset"),
+ {}, {opts.extStackOffset});
+}
+
+void Mcs51GeneralSettingsGroup::buildDataPointerPage(
+ const ProductData &qbsProduct)
+{
+ const DptrPageOptions opts(qbsProduct);
+ // Add 'Nr of Datapointers' item (Number of DPTRs: 1...8).
+ addOptionsGroup(QByteArrayLiteral("Nr of Datapointers"),
+ {}, {opts.dptrsCountIndex});
+ // Add 'Datapointer Size' item (DPTR size: 16/24).
+ addOptionsGroup(QByteArrayLiteral("Datapointer Size"),
+ {}, {opts.dptrSize});
+ // Add 'Sfr Visibility' item (DPTR address: shadowed/separate).
+ addOptionsGroup(QByteArrayLiteral("Sfr Visibility"),
+ {}, {opts.dptrVisibility});
+ // Add 'Switch Method' item (Switch method: inc/mask).
+ addOptionsGroup(QByteArrayLiteral("Switch Method"),
+ {}, {opts.dptrSwitchMethod});
+ // Add 'Mask Value' item (Switch method mask).
+ addOptionsGroup(QByteArrayLiteral("Mask Value"),
+ {}, {opts.dptrMask});
+ // Add 'PDATA 8-15 register address' item (Page register
+ // address (for bits 8-15).
+ addOptionsGroup(QByteArrayLiteral("PDATA 8-15 register address"),
+ {}, {opts.dptrPbank});
+ // Add 'PDATA 16-31 register address' item (Page register
+ // address (for bits 16-31).
+ addOptionsGroup(QByteArrayLiteral("PDATA 16-31 register address"),
+ {}, {opts.dptrPbankExt});
+ // Add 'DPS Address' item (Selected DPTR register).
+ addOptionsGroup(QByteArrayLiteral("DPS Address"),
+ {}, {opts.dpsAddress});
+ // Add 'DPC Address' item (Separate DPTR control register).
+ addOptionsGroup(QByteArrayLiteral("DPC Address"),
+ {}, {opts.dpcAddress});
+ // Add 'DPTR Addresses' item (DPTR addresses: Low/High/Ext).
+ const QString dptrAddresses = opts.dptrAddresses.join(QLatin1Char(' '));
+ addOptionsGroup(QByteArrayLiteral("DPTR Addresses"),
+ {}, {dptrAddresses});
+}
+
+void Mcs51GeneralSettingsGroup::buildCodeBankPage(
+ const ProductData &qbsProduct)
+{
+ const CodeBankPageOptions opts(qbsProduct);
+ // Add 'CodeBankReg' item (Register address).
+ addOptionsGroup(QByteArrayLiteral("CodeBankReg"),
+ {}, {opts.registerAddress});
+ // Add 'CodeBankRegMask' item (Register mask).
+ addOptionsGroup(QByteArrayLiteral("CodeBankRegMask"),
+ {}, {opts.registerMask});
+ // Add 'CodeBankNrOfs' item (Number of banks).
+ addOptionsGroup(QByteArrayLiteral("CodeBankNrOfs"),
+ {}, {opts.banksCount});
+ // Add 'CodeBankStart' item (Bank start).
+ addOptionsGroup(QByteArrayLiteral("CodeBankStart"),
+ {}, {opts.bankStart});
+ // Add 'CodeBankSize' item (Bank end).
+ addOptionsGroup(QByteArrayLiteral("CodeBankSize"),
+ {}, {opts.bankEnd});
+}
+
+void Mcs51GeneralSettingsGroup::buildLibraryOptionsPage(
+ const ProductData &qbsProduct)
+{
+ const LibraryOptionsPageOptions opts(qbsProduct);
+ // Add 'Output variant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("Output variant"),
+ {}, {opts.printfFormatter});
+ // Add 'Input variant' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("Input variant"),
+ {}, {opts.scanfFormatter});
+}
+
+void Mcs51GeneralSettingsGroup::buildLibraryConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const LibraryConfigPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GRuntimeLibSelect2' and 'GRuntimeLibSelectSlave2' items
+ // (Link with runtime: none/dlib/clib/etc).
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect2"),
+ {}, {opts.libraryType});
+ addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave2"),
+ {}, {opts.libraryType});
+ // Add 'RTConfigPath' item (Runtime configuration file).
+ addOptionsGroup(QByteArrayLiteral("RTConfigPath"),
+ {}, {opts.configPath});
+ // Add 'RTLibraryPath' item (Runtime library file).
+ addOptionsGroup(QByteArrayLiteral("RTLibraryPath"),
+ {}, {opts.libraryPath});
+}
+
+void Mcs51GeneralSettingsGroup::buildOutputPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GOutputBinary' item (Output file: executable/library).
+ addOptionsGroup(QByteArrayLiteral("GOutputBinary"),
+ {}, {opts.binaryType});
+ // Add 'ExePath' item (Executable/binaries output directory).
+ addOptionsGroup(QByteArrayLiteral("ExePath"),
+ {}, {opts.binaryDirectory});
+ // Add 'ObjPath' item (Object files output directory).
+ addOptionsGroup(QByteArrayLiteral("ObjPath"),
+ {}, {opts.objectDirectory});
+ // Add 'ListPath' item (List files output directory).
+ addOptionsGroup(QByteArrayLiteral("ListPath"),
+ {}, {opts.listingDirectory});
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h
new file mode 100644
index 000000000..1805a87af
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H
+#define QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51GeneralSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Mcs51GeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildTargetPage(const ProductData &qbsProduct);
+ void buildStackHeapPage(const ProductData &qbsProduct);
+ void buildDataPointerPage(const ProductData &qbsProduct);
+ void buildCodeBankPage(const ProductData &qbsProduct);
+ void buildLibraryOptionsPage(const ProductData &qbsProduct);
+ void buildLibraryConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp
new file mode 100644
index 000000000..c27fa51f2
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51linkersettingsgroup_v10.h"
+
+#include "../../iarewutils.h"
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+constexpr int kLinkerArchiveVersion = 4;
+constexpr int kLinkerDataVersion = 21;
+
+namespace {
+
+// Config page options.
+
+struct ConfigPageOptions final
+{
+ explicit ConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+
+ entryPoint = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("entryPoint"));
+
+ // Enumerate all product linker config files
+ // (which are set trough 'linkerscript' tag).
+ const auto qbsGroups = qbsProduct.groups();
+ for (const auto &qbsGroup : qbsGroups) {
+ const auto qbsArtifacts = qbsGroup.sourceArtifacts();
+ for (const auto &qbsArtifact : qbsArtifacts) {
+ const auto qbsTags = qbsArtifact.fileTags();
+ if (!qbsTags.contains(QLatin1String("linkerscript")))
+ continue;
+ const QString fullConfigPath = qbsArtifact.filePath();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ configFilePaths.push_back(path);
+ }
+ }
+ }
+
+ // Enumerate all product linker config files
+ // (which are set trough '-f' option).
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ const QVariantList configPathValues = IarewUtils::flagValues(
+ flags, QStringLiteral("-f"));
+ for (const QVariant &configPathValue : configPathValues) {
+ const QString fullConfigPath = configPathValue.toString();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ } else {
+ const QString path =IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ }
+ }
+
+ // Add libraries search paths.
+ const QStringList libraryPaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("libraryPaths")});
+ for (const QString &libraryPath : libraryPaths) {
+ const QFileInfo libraryPathInfo(libraryPath);
+ const QString fullLibrarySearchPath = libraryPathInfo.absoluteFilePath();
+ if (fullLibrarySearchPath.startsWith(toolkitPath,
+ Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullLibrarySearchPath);
+ librarySearchPaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList configFilePaths;
+ QVariantList librarySearchPaths;
+ QString entryPoint;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ outputFile = gen::utils::targetBinary(qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+// List page options.
+
+struct ListPageOptions final
+{
+ enum ListingAction {
+ NoListing,
+ GenerateListing
+ };
+
+ explicit ListPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ generateMap = gen::utils::cppBooleanModuleProperty(
+ qbsProps, QStringLiteral("generateMapFile"))
+ ? ListPageOptions::GenerateListing
+ : ListPageOptions::NoListing;
+ }
+
+ ListingAction generateMap = NoListing;
+};
+
+// Define page options.
+
+struct DefinePageOptions final
+{
+ explicit DefinePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ // Enumerate all linker defines.
+ for (const QString &flag : flags) {
+ if (!flag.startsWith(QLatin1String("-D")))
+ continue;
+ const QString symbol = flag.mid(2);
+ // Ignore system-defined macroses, because its already
+ // handled in "General Options" page.
+ if (symbol.startsWith(QLatin1Char('?'))
+ || symbol.startsWith(QLatin1Char('_'))
+ ) {
+ continue;
+ }
+ defineSymbols.push_back(symbol);
+ }
+ }
+
+ QVariantList defineSymbols;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString warningLevel = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ suppressAllWarnings = (warningLevel == QLatin1String("none"));
+ }
+
+ int suppressAllWarnings = 0;
+};
+
+} // namespace
+
+// Mcs51LinkerSettingsGroup
+
+Mcs51LinkerSettingsGroup::Mcs51LinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("XLINK"));
+ setArchiveVersion(kLinkerArchiveVersion);
+ setDataVersion(kLinkerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildConfigPage(buildRootDirectory, qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildListPage(qbsProduct);
+ buildDefinePage(qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+
+ // Should be called as latest stage!
+ buildExtraOptionsPage(qbsProduct);
+}
+
+void Mcs51LinkerSettingsGroup::buildConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ ConfigPageOptions opts(baseDirectory, qbsProduct);
+
+ if (opts.configFilePaths.count() > 0) {
+ // Note: IAR IDE does not allow to specify a multiple config files,
+ // although the IAR linker support it. So, we use followig 'trick':
+ // we take a first config file and to add it as usual to required items;
+ // and then an other remainders we forward to the "Extra options page".
+ const QVariant configPath = opts.configFilePaths.takeFirst();
+ // Add 'XclOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("XclOverride"),
+ {}, {1});
+ // Add 'XclFile' item (Linke configuration file).
+ addOptionsGroup(QByteArrayLiteral("XclFile"),
+ {}, {configPath});
+
+ // Add remainder configuration files to the "Extra options page".
+ if (!opts.configFilePaths.isEmpty()) {
+ for (QVariant &configPath : opts.configFilePaths)
+ configPath = QLatin1String("-f ") + configPath.toString();
+
+ m_extraOptions << opts.configFilePaths;
+ }
+ }
+
+ // Add 'xcProgramEntryLabel' item (Entry symbol).
+ addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"),
+ {}, {opts.entryPoint});
+ // Add 'xcOverrideProgramEntryLabel' item
+ // (Override default program entry).
+ addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"),
+ {}, {1});
+ // Add 'xcProgramEntryLabelSelect' item.
+ addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"),
+ {}, {0});
+
+ // Add 'XIncludes' item (Libraries search paths).
+ addOptionsGroup(QByteArrayLiteral("XIncludes"),
+ {}, opts.librarySearchPaths);
+}
+
+void Mcs51LinkerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'XOutOverride' item (Override default output file).
+ addOptionsGroup(QByteArrayLiteral("XOutOverride"),
+ {}, {1});
+ // Add 'OutputFile' item (Output file name).
+ addOptionsGroup(QByteArrayLiteral("OutputFile"),
+ {}, {opts.outputFile});
+}
+
+void Mcs51LinkerSettingsGroup::buildListPage(
+ const ProductData &qbsProduct)
+{
+ const ListPageOptions opts(qbsProduct);
+ // Add 'XList' item (Generate linker listing).
+ addOptionsGroup(QByteArrayLiteral("XList"),
+ {}, {opts.generateMap});
+}
+
+void Mcs51LinkerSettingsGroup::buildDefinePage(
+ const ProductData &qbsProduct)
+{
+ const DefinePageOptions opts(qbsProduct);
+ // Add 'XDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("XDefines"),
+ {}, opts.defineSymbols);
+}
+
+void Mcs51LinkerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'SuppressAllWarn' item (Suppress all warnings).
+ addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"),
+ {}, {opts.suppressAllWarnings});
+}
+
+void Mcs51LinkerSettingsGroup::buildExtraOptionsPage(
+ const ProductData &qbsProduct)
+{
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ for (const QString &flag : flags) {
+ if (flag.startsWith(QLatin1String("-Z")))
+ m_extraOptions.push_back(flag);
+ }
+
+ if (!m_extraOptions.isEmpty()) {
+ // Add 'Linker Extra Options Check' (Use command line options).
+ addOptionsGroup(QByteArrayLiteral("Linker Extra Options Check"),
+ {}, {1});
+ // Add 'Linker Extra Options Edit' item (Command line options).
+ addOptionsGroup(QByteArrayLiteral("Linker Extra Options Edit"),
+ {}, m_extraOptions);
+ }
+}
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h
new file mode 100644
index 000000000..fec80e5e6
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H
+#define QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace mcs51 {
+namespace v10 {
+
+class Mcs51LinkerSettingsGroupPrivate;
+
+class Mcs51LinkerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Mcs51LinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildListPage(const ProductData &qbsProduct);
+ void buildDefinePage(const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildExtraOptionsPage(const ProductData &qbsProduct);
+
+ QVariantList m_extraOptions;
+};
+
+} // namespace v10
+} // namespace mcs51
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp
new file mode 100644
index 000000000..8a2ab0011
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8archiversettingsgroup_v3.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+constexpr int kArchiverArchiveVersion = 3;
+constexpr int kArchiverDataVersion = 0;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ outputFile = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory, qbsProduct);
+ }
+
+ QString outputFile;
+};
+
+} // namespace
+
+// Stm8ArchiverSettingsGroup
+
+Stm8ArchiverSettingsGroup::Stm8ArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("IARCHIVE"));
+ setArchiveVersion(kArchiverArchiveVersion);
+ setDataVersion(kArchiverDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+}
+
+void Stm8ArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'IarchiveOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("IarchiveOverride"),
+ {}, {1});
+ // Add 'IarchiveOutput' item (Output filename).
+ addOptionsGroup(QByteArrayLiteral("IarchiveOutput"),
+ {}, {opts.outputFile});
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h
new file mode 100644
index 000000000..754add3cb
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H
+#define QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8ArchiverSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Stm8ArchiverSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp
new file mode 100644
index 000000000..1e4e93706
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8assemblersettingsgroup_v3.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+constexpr int kAssemblerArchiveVersion = 3;
+constexpr int kAssemblerDataVersion = 2;
+
+namespace {
+
+// Language page options.
+
+struct LanguagePageOptions final
+{
+ enum MacroQuoteCharacter {
+ AngleBracketsQuote,
+ RoundBracketsQuote,
+ SquareBracketsQuote,
+ FigureBracketsQuote
+ };
+
+ explicit LanguagePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("assemblerFlags")});
+ enableSymbolsCaseSensitive = !flags.contains(
+ QLatin1String("--case_insensitive"));
+ enableMultibyteSupport = flags.contains(
+ QLatin1String("--enable_multibytes"));
+ allowFirstColumnMnemonics = flags.contains(
+ QLatin1String("--mnem_first"));
+ allowFirstColumnDirectives = flags.contains(
+ QLatin1String("--dir_first"));
+
+ if (flags.contains(QLatin1String("-M<>")))
+ macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote;
+ else if (flags.contains(QLatin1String("-M()")))
+ macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote;
+ else if (flags.contains(QLatin1String("-M[]")))
+ macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote;
+ else if (flags.contains(QLatin1String("-M{}")))
+ macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote;
+ }
+
+ int enableSymbolsCaseSensitive = 1;
+ int enableMultibyteSupport = 0;
+ int allowFirstColumnMnemonics = 0;
+ int allowFirstColumnDirectives = 0;
+
+ MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const auto &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ warningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int warningsAsErrors = 0;
+};
+
+} // namespace
+
+// Stm8AssemblerSettingsGroup
+
+Stm8AssemblerSettingsGroup::Stm8AssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("ASTM8"));
+ setArchiveVersion(kAssemblerArchiveVersion);
+ setDataVersion(kAssemblerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildLanguagePage(qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void Stm8AssemblerSettingsGroup::buildLanguagePage(
+ const ProductData &qbsProduct)
+{
+ const LanguagePageOptions opts(qbsProduct);
+ // Add 'AsmCaseSensitivity' item (User symbols are case sensitive).
+ addOptionsGroup(QByteArrayLiteral("AsmCaseSensitivity"),
+ {}, {opts.enableSymbolsCaseSensitive});
+ // Add 'AsmMultibyteSupport' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("AsmMultibyteSupport"),
+ {}, {opts.enableMultibyteSupport});
+ // Add 'AsmAllowMnemonics' item (Allow mnemonics in first column).
+ addOptionsGroup(QByteArrayLiteral("AsmAllowMnemonics"),
+ {}, {opts.allowFirstColumnMnemonics});
+ // Add 'AsmAllowDirectives' item (Allow directives in first column).
+ addOptionsGroup(QByteArrayLiteral("AsmAllowDirectives"),
+ {}, {opts.allowFirstColumnDirectives});
+
+ // Add 'AsmMacroChars' item (Macro quote characters: ()/[]/{}/<>).
+ addOptionsGroup(QByteArrayLiteral("AsmMacroChars"),
+ {0}, {opts.macroQuoteCharacter});
+}
+
+void Stm8AssemblerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'AsmDebugInfo' item (Generate debug information).
+ addOptionsGroup(QByteArrayLiteral("AsmDebugInfo"),
+ {}, {opts.debugInfo});
+}
+
+void Stm8AssemblerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'AsmDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("AsmDefines"),
+ {}, opts.defineSymbols);
+ // Add 'AsmIncludePath' item (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("AsmIncludePath"),
+ {}, opts.includePaths);
+}
+
+void Stm8AssemblerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'AsmDiagnosticsWarningsAreErrors' item.
+ // (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("AsmDiagnosticsWarningsAreErrors"),
+ {}, {opts.warningsAsErrors});
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h
new file mode 100644
index 000000000..4d7d0485b
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H
+#define QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8AssemblerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Stm8AssemblerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildLanguagePage(const ProductData &qbsProduct);
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp
new file mode 100644
index 000000000..06167f919
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8archiversettingsgroup_v3.h"
+#include "stm8assemblersettingsgroup_v3.h"
+#include "stm8buildconfigurationgroup_v3.h"
+#include "stm8compilersettingsgroup_v3.h"
+#include "stm8generalsettingsgroup_v3.h"
+#include "stm8linkersettingsgroup_v3.h"
+
+#include "../../iarewtoolchainpropertygroup.h"
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+Stm8BuildConfigurationGroup::Stm8BuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup("configuration")
+{
+ // Append configuration name item.
+ const QString cfgName = gen::utils::buildConfigurationName(qbsProject);
+ appendProperty("name", cfgName);
+
+ // Apend toolchain name group item.
+ appendChild<IarewToolchainPropertyGroup>("STM8");
+
+ // Append debug info item.
+ const int debugBuild = gen::utils::debugInformation(qbsProduct);
+ appendProperty("debug", debugBuild);
+
+ // Append settings group items.
+ appendChild<Stm8ArchiverSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Stm8AssemblerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Stm8CompilerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Stm8GeneralSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild<Stm8LinkerSettingsGroup>(
+ qbsProject, qbsProduct, qbsProductDeps);
+}
+
+bool Stm8BuildConfigurationGroupFactory::canCreate(
+ gen::utils::Architecture arch,
+ const Version &version) const
+{
+ return arch == gen::utils::Architecture::Stm8
+ && version.majorVersion() == 3;
+}
+
+std::unique_ptr<gen::xml::PropertyGroup>
+Stm8BuildConfigurationGroupFactory::create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const
+{
+ const auto group = new Stm8BuildConfigurationGroup(
+ qbsProject, qbsProduct, qbsProductDeps);
+ return std::unique_ptr<Stm8BuildConfigurationGroup>(group);
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h
new file mode 100644
index 000000000..c47819fef
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H
+#define QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H
+
+#include <generators/generatorutils.h>
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8BuildConfigurationGroup final
+ : public gen::xml::PropertyGroup
+{
+private:
+ explicit Stm8BuildConfigurationGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+ friend class Stm8BuildConfigurationGroupFactory;
+};
+
+class Stm8BuildConfigurationGroupFactory final
+ : public gen::xml::PropertyGroupFactory
+{
+public:
+ bool canCreate(gen::utils::Architecture arch,
+ const Version &version) const final;
+
+ std::unique_ptr<gen::xml::PropertyGroup> create(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps) const final;
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp
new file mode 100644
index 000000000..23cb059a4
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp
@@ -0,0 +1,442 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8compilersettingsgroup_v3.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+constexpr int kCompilerArchiveVersion = 3;
+constexpr int kCompilerDataVersion = 9;
+
+namespace {
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+ }
+
+ int debugInfo = 0;
+};
+
+// Language one page options.
+
+struct LanguageOnePageOptions final
+{
+ enum LanguageExtension {
+ CLanguageExtension,
+ CxxLanguageExtension,
+ AutoLanguageExtension
+ };
+
+ enum CLanguageDialect {
+ C89LanguageDialect,
+ C99LanguageDialect
+ };
+
+ enum CxxLanguageDialect {
+ EmbeddedCPlusPlus,
+ ExtendedEmbeddedCPlusPlus
+ };
+
+ enum LanguageConformance {
+ AllowIarExtension,
+ RelaxedStandard,
+ StrictStandard
+ };
+
+ explicit LanguageOnePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ // File extension based by default.
+ languageExtension = LanguageOnePageOptions::AutoLanguageExtension;
+ // C language dialect.
+ const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("cLanguageVersion")});
+ if (cLanguageVersion.contains(QLatin1String("c89")))
+ cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect;
+ else if (cLanguageVersion.contains(QLatin1String("c99")))
+ cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect;
+ // C++ language dialect.
+ if (flags.contains(QLatin1String("--ec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus;
+ else if (flags.contains(QLatin1String("--eec++")))
+ cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus;
+ // Language conformance.
+ if (flags.contains(QLatin1String("-e")))
+ languageConformance = LanguageOnePageOptions::AllowIarExtension;
+ else if (flags.contains(QLatin1String("--strict")))
+ languageConformance = LanguageOnePageOptions::StrictStandard;
+ else
+ languageConformance = LanguageOnePageOptions::RelaxedStandard;
+
+ allowVla = flags.contains(QLatin1String("--vla"));
+ useCppInlineSemantics = flags.contains(
+ QLatin1String("--use_c++_inline"));
+ requirePrototypes = flags.contains(
+ QLatin1String("--require_prototypes"));
+ destroyStaticObjects = !flags.contains(
+ QLatin1String("--no_static_destruction"));
+ }
+
+ LanguageExtension languageExtension = AutoLanguageExtension;
+ CLanguageDialect cLanguageDialect = C99LanguageDialect;
+ CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus;
+ LanguageConformance languageConformance = AllowIarExtension;
+ int allowVla = 0;
+ int useCppInlineSemantics = 0;
+ int requirePrototypes = 0;
+ int destroyStaticObjects = 0;
+};
+
+// Language two page options.
+
+struct LanguageTwoPageOptions final
+{
+ enum PlainCharacter {
+ SignedCharacter,
+ UnsignedCharacter
+ };
+
+ enum FloatingPointSemantic {
+ StrictSemantic,
+ RelaxedSemantic
+ };
+
+ explicit LanguageTwoPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+ plainCharacter = flags.contains(QLatin1String("--char_is_signed"))
+ ? LanguageTwoPageOptions::SignedCharacter
+ : LanguageTwoPageOptions::UnsignedCharacter;
+ floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp"))
+ ? LanguageTwoPageOptions::RelaxedSemantic
+ : LanguageTwoPageOptions::StrictSemantic;
+ enableMultibyteSupport = flags.contains(
+ QLatin1String("--enable_multibytes"));
+ }
+
+ PlainCharacter plainCharacter = UnsignedCharacter;
+ FloatingPointSemantic floatingPointSemantic = StrictSemantic;
+ int enableMultibyteSupport = 0;
+};
+
+// Optimizations page options.
+
+struct OptimizationsPageOptions final
+{
+ // Optimizations level radio-buttons with
+ // combo-box on "level" widget.
+ enum Strategy {
+ StrategyBalanced,
+ StrategySize,
+ StrategySpeed
+ };
+
+ enum Level {
+ LevelNone,
+ LevelLow,
+ LevelMedium,
+ LevelHigh
+ };
+
+ enum LevelSlave {
+ LevelSlave0,
+ LevelSlave1,
+ LevelSlave2,
+ LevelSlave3
+ };
+
+ enum VRegsNumber {
+ VRegs12,
+ VRegs16
+ };
+
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString optimization = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("optimization"));
+ if (optimization == QLatin1String("none")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategyBalanced;
+ optimizationLevel = OptimizationsPageOptions::LevelNone;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0;
+ } else if (optimization == QLatin1String("fast")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySpeed;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ } else if (optimization == QLatin1String("small")) {
+ optimizationStrategy = OptimizationsPageOptions::StrategySize;
+ optimizationLevel = OptimizationsPageOptions::LevelHigh;
+ optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3;
+ }
+
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ disableSizeConstraints = flags.contains(
+ QLatin1String("--no_size_constraints"));
+
+ enableCommonSubexpressionElimination = !flags.contains(
+ QLatin1String("--no_cse"));
+ enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll"));
+ enableFunctionInlining = !flags.contains(QLatin1String("--no_inline"));
+ enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion"));
+ enableTypeBasedAliasAnalysis = !flags.contains(
+ QLatin1String("--no_tbaa"));
+ enableCrossCall = !flags.contains(QLatin1String("--no_cross_call"));
+
+ const auto vregsCount = IarewUtils::flagValue(
+ flags, QStringLiteral("--vregs")).toInt();
+ if (vregsCount == 12)
+ vregsNumber = VRegs12;
+ else if (vregsCount == 16)
+ vregsNumber = VRegs16;
+ }
+
+ Strategy optimizationStrategy = StrategyBalanced;
+ Level optimizationLevel = LevelNone;
+ LevelSlave optimizationLevelSlave = LevelSlave0;
+ // Separate "no size constraints" checkbox.
+ int disableSizeConstraints = 0;
+
+ // Six bit-field flags on "enabled transformations" widget.
+ int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination.
+ int enableLoopUnroll = 0; // Loop unrolling.
+ int enableFunctionInlining = 0; // Function inlining.
+ int enableCodeMotion = 0; // Code motion.
+ int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis.
+ int enableCrossCall = 0; // Cross call.
+
+ VRegsNumber vregsNumber = VRegs16;
+};
+
+// Preprocessor page options.
+
+struct PreprocessorPageOptions final
+{
+ explicit PreprocessorPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ defineSymbols = gen::utils::cppVariantModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+ const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ for (const QString &fullIncludePath : fullIncludePaths) {
+ const QFileInfo includeFileInfo(fullIncludePath);
+ const QString includeFilePath = includeFileInfo.absoluteFilePath();
+ if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, includeFilePath);
+ includePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, includeFilePath);
+ includePaths.push_back(path);
+ }
+ }
+ }
+
+ QVariantList defineSymbols;
+ QVariantList includePaths;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ warningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int warningsAsErrors = 0;
+};
+
+} // namespace
+
+// Stm8CompilerSettingsGroup
+
+Stm8CompilerSettingsGroup::Stm8CompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("ICCSTM8"));
+ setArchiveVersion(kCompilerArchiveVersion);
+ setDataVersion(kCompilerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildOutputPage(qbsProduct);
+ buildLanguageOnePage(qbsProduct);
+ buildLanguageTwoPage(qbsProduct);
+ buildOptimizationsPage(qbsProduct);
+ buildPreprocessorPage(buildRootDirectory, qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+}
+
+void Stm8CompilerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+ // Add 'IccGenerateDebugInfo' item (Generate debug info).
+ addOptionsGroup(QByteArrayLiteral("IccGenerateDebugInfo"),
+ {}, {opts.debugInfo});
+}
+
+void Stm8CompilerSettingsGroup::buildLanguageOnePage(
+ const ProductData &qbsProduct)
+{
+ const LanguageOnePageOptions opts(qbsProduct);
+ // Add 'IccLang' item with 'auto-extension based'
+ // value (Language: C/C++/Auto).
+ addOptionsGroup(QByteArrayLiteral("IccLang"),
+ {}, {opts.languageExtension});
+ // Add 'IccCDialect' item (C dialect: c89/99/11).
+ addOptionsGroup(QByteArrayLiteral("IccCDialect"),
+ {}, {opts.cLanguageDialect});
+ // Add 'IccCppDialect' item (C++ dialect: embedded/extended).
+ addOptionsGroup(QByteArrayLiteral("IccCppDialect"),
+ {}, {opts.cxxLanguageDialect});
+ // Add 'IccLanguageConformance' item
+ // (Language conformance: IAR/relaxed/strict).
+ addOptionsGroup(QByteArrayLiteral("IccLanguageConformance"),
+ {}, {opts.languageConformance});
+ // Add 'IccAllowVLA' item (Allow VLA).
+ addOptionsGroup(QByteArrayLiteral("IccAllowVLA"),
+ {}, {opts.allowVla});
+ // Add 'IccCppInlineSemantics' item (C++ inline semantics).
+ addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"),
+ {}, {opts.useCppInlineSemantics});
+ // Add 'IccRequirePrototypes' item (Require prototypes).
+ addOptionsGroup(QByteArrayLiteral("IccRequirePrototypes"),
+ {}, {opts.requirePrototypes});
+ // Add 'IccStaticDestr' item (Destroy static objects).
+ addOptionsGroup(QByteArrayLiteral("IccStaticDestr"),
+ {}, {opts.destroyStaticObjects});
+}
+
+void Stm8CompilerSettingsGroup::buildLanguageTwoPage(
+ const ProductData &qbsProduct)
+{
+ const LanguageTwoPageOptions opts(qbsProduct);
+ // Add 'IccCharIs' item (Plain char is: signed/unsigned).
+ addOptionsGroup(QByteArrayLiteral("IccCharIs"),
+ {}, {opts.plainCharacter});
+ // Add 'IccFloatSemantics' item (Floatic-point
+ // semantics: strict/relaxed conformance).
+ addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"),
+ {}, {opts.floatingPointSemantic});
+ // Add 'IccMultibyteSupport' item (Enable multibyte support).
+ addOptionsGroup(QByteArrayLiteral("IccMultibyteSupport"),
+ {}, {opts.enableMultibyteSupport});
+}
+
+void Stm8CompilerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ const OptimizationsPageOptions opts(qbsProduct);
+ // Add 'IccOptStrategy', 'IccOptLevel' and
+ // 'CCOptLevelSlave' items (Level).
+ addOptionsGroup(QByteArrayLiteral("IccOptStrategy"),
+ {}, {opts.optimizationStrategy});
+ addOptionsGroup(QByteArrayLiteral("IccOptLevel"),
+ {}, {opts.optimizationLevel});
+ addOptionsGroup(QByteArrayLiteral("IccOptLevelSlave"),
+ {}, {opts.optimizationLevelSlave});
+
+ // Add 'IccOptNoSizeConstraints' iten (no size constraints).
+ addOptionsGroup(QByteArrayLiteral("IccOptNoSizeConstraints"),
+ {}, {opts.disableSizeConstraints});
+
+ // Add 'IccOptAllowList' item
+ // (Enabled optimizations: 6 check boxes).
+ const QString bitflags = QStringLiteral("%1%2%3%4%5%6")
+ .arg(opts.enableCommonSubexpressionElimination)
+ .arg(opts.enableLoopUnroll)
+ .arg(opts.enableFunctionInlining)
+ .arg(opts.enableCodeMotion)
+ .arg(opts.enableTypeBasedAliasAnalysis)
+ .arg(opts.enableCrossCall);
+ addOptionsGroup(QByteArrayLiteral("IccOptAllowList"),
+ {}, {bitflags});
+
+ // Add 'IccNoVregs' item
+ // (Number of virtual registers (12/16).
+ addOptionsGroup(QByteArrayLiteral("IccNoVregs"),
+ {}, {opts.vregsNumber});
+}
+
+void Stm8CompilerSettingsGroup::buildPreprocessorPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const PreprocessorPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'CCDefines' item (Defines symbols).
+ addOptionsGroup(QByteArrayLiteral("CCDefines"),
+ {}, opts.defineSymbols);
+ // Add 'CCIncludePath2' item
+ // (Additional include directories).
+ addOptionsGroup(QByteArrayLiteral("CCIncludePath2"),
+ {}, opts.includePaths);
+}
+
+void Stm8CompilerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"),
+ {}, {opts.warningsAsErrors});
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h
new file mode 100644
index 000000000..48545b86d
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.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_IAREWSTM8COMPILERSETTINGSGROUP_V3_H
+#define QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8CompilerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Stm8CompilerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildLanguageOnePage(const ProductData &qbsProduct);
+ void buildLanguageTwoPage(const ProductData &qbsProduct);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+ void buildPreprocessorPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildCodePage(const ProductData &qbsProduct);
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp
new file mode 100644
index 000000000..8dff5a7dd
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8generalsettingsgroup_v3.h"
+
+#include "../../iarewutils.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+constexpr int kGeneralArchiveVersion = 4;
+constexpr int kGeneralDataVersion = 2;
+
+namespace {
+
+// Target page options.
+
+struct TargetPageOptions final
+{
+ enum CodeModel {
+ SmallCodeModel,
+ MediumCodeModel,
+ LargeCodeModel
+ };
+
+ enum DataModel {
+ SmallDataModel,
+ MediumDataModel,
+ LargeDataModel
+ };
+
+ explicit TargetPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags")});
+ // Detect target code model.
+ const QString codeModelValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--code_model"));
+ if (codeModelValue == QLatin1String("small"))
+ codeModel = TargetPageOptions::SmallCodeModel;
+ else if (codeModelValue == QLatin1String("medium"))
+ codeModel = TargetPageOptions::MediumCodeModel;
+ else if (codeModelValue == QLatin1String("large"))
+ codeModel = TargetPageOptions::LargeCodeModel;
+ // Detect target data model.
+ const QString dataModelValue = IarewUtils::flagValue(
+ flags, QStringLiteral("--code_model"));
+ if (dataModelValue == QLatin1String("small"))
+ dataModel = TargetPageOptions::SmallDataModel;
+ else if (dataModelValue == QLatin1String("medium"))
+ dataModel = TargetPageOptions::MediumDataModel;
+ else if (dataModelValue == QLatin1String("large"))
+ dataModel = TargetPageOptions::LargeDataModel;
+ }
+
+ CodeModel codeModel = MediumCodeModel;
+ DataModel dataModel = MediumDataModel;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ binaryType = IarewUtils::outputBinaryType(qbsProduct);
+ binaryDirectory = gen::utils::binaryOutputDirectory(
+ baseDirectory, qbsProduct);
+ objectDirectory = gen::utils::objectsOutputDirectory(
+ baseDirectory, qbsProduct);
+ listingDirectory = gen::utils::listingOutputDirectory(
+ baseDirectory, qbsProduct);
+ }
+
+ IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType;
+ QString binaryDirectory;
+ QString objectDirectory;
+ QString listingDirectory;
+};
+
+// Library configuration page options.
+
+struct LibraryConfigPageOptions final
+{
+ enum RuntimeLibrary {
+ NoLibrary,
+ NormalLibrary,
+ FullLibrary,
+ CustomLibrary
+ };
+
+ explicit LibraryConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps);
+
+ const QFileInfo configInfo(IarewUtils::flagValue(
+ flags,
+ QStringLiteral("--dlib_config")));
+ const QString configFilePath = configInfo.absoluteFilePath();
+
+ if (!configFilePath.isEmpty()) {
+ const QString libToolkitPath =
+ IarewUtils::libToolkitRootPath(qbsProduct);
+
+ if (configFilePath.startsWith(libToolkitPath,
+ Qt::CaseInsensitive)) {
+ if (configFilePath.endsWith(QLatin1String("n.h"),
+ Qt::CaseInsensitive)) {
+ libraryType = LibraryConfigPageOptions::NormalLibrary;
+ } else if (configFilePath.endsWith(QLatin1String("f.h"),
+ Qt::CaseInsensitive)) {
+ libraryType = LibraryConfigPageOptions::FullLibrary;
+ } else {
+ libraryType = LibraryConfigPageOptions::CustomLibrary;
+ }
+
+ configPath = IarewUtils::toolkitRelativeFilePath(
+ baseDirectory, configFilePath);
+ } else {
+ libraryType = LibraryConfigPageOptions::CustomLibrary;
+
+ configPath = configFilePath;
+ }
+ } else {
+ libraryType = LibraryConfigPageOptions::NoLibrary;
+ }
+ }
+
+ RuntimeLibrary libraryType = NoLibrary;
+ QString configPath;
+};
+
+// Library options page options.
+
+struct LibraryOptionsPageOptions final
+{
+ enum PrintfFormatter {
+ PrintfAutoFormatter = 0,
+ PrintfFullFormatter = 1,
+ PrintfFullNoMultibytesFormatter = 2,
+ PrintfLargeFormatter = 3,
+ PrintfLargeNoMultibytesFormatter = 4,
+ PrintfSmallFormatter = 5,
+ PrintfSmallNoMultibytesFormatter = 6,
+ PrintfTinyFormatter = 7
+ };
+
+ enum ScanfFormatter {
+ ScanfAutoFormatter = 0,
+ ScanfFullFormatter = 1,
+ ScanfFullNoMultibytesFormatter = 2,
+ ScanfLargeFormatter = 3,
+ ScanfLargeNoMultibytesFormatter = 4,
+ ScanfSmallFormatter = 5,
+ ScanfSmallNoMultibytesFormatter = 6
+ };
+
+ explicit LibraryOptionsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) {
+ if (*flagIt != QLatin1String("--redirect"))
+ continue;
+ ++flagIt;
+ if (flagIt->startsWith(QLatin1String("_printf="),
+ Qt::CaseInsensitive)) {
+ const QString prop = flagIt->split(
+ QLatin1Char('=')).at(1).toLower();
+ if (prop == QLatin1String("_printffull"))
+ printfFormatter = PrintfFullFormatter;
+ else if (prop == QLatin1String("_printffullnomb"))
+ printfFormatter = PrintfFullNoMultibytesFormatter;
+ else if (prop == QLatin1String("_printflarge"))
+ printfFormatter = PrintfLargeFormatter;
+ else if (prop == QLatin1String("_printflargenomb"))
+ printfFormatter = PrintfLargeFormatter;
+ else if (prop == QLatin1String("_printfsmall"))
+ printfFormatter = PrintfSmallFormatter;
+ else if (prop == QLatin1String("_printfsmallnomb"))
+ printfFormatter = PrintfSmallNoMultibytesFormatter;
+ else if (prop == QLatin1String("_printftiny"))
+ printfFormatter = PrintfTinyFormatter;
+ } else if (flagIt->startsWith(QLatin1String("_scanf="),
+ Qt::CaseInsensitive)) {
+ const QString prop = flagIt->split(
+ QLatin1Char('=')).at(1).toLower();
+ if (prop == QLatin1String("_scanffull"))
+ scanfFormatter = ScanfFullFormatter;
+ else if (prop == QLatin1String("_scanffullnomb"))
+ scanfFormatter = ScanfFullNoMultibytesFormatter;
+ else if (prop == QLatin1String("_scanflarge"))
+ scanfFormatter = ScanfLargeFormatter;
+ else if (prop == QLatin1String("_scanflargenomb"))
+ scanfFormatter = ScanfLargeFormatter;
+ else if (prop == QLatin1String("_scanfsmall"))
+ scanfFormatter = ScanfSmallFormatter;
+ else if (prop == QLatin1String("_scanfsmallnomb"))
+ scanfFormatter = ScanfSmallNoMultibytesFormatter;
+ }
+ }
+ }
+
+ PrintfFormatter printfFormatter = PrintfAutoFormatter;
+ ScanfFormatter scanfFormatter = ScanfAutoFormatter;
+};
+
+// Stack/heap page options.
+
+struct StackHeapPageOptions final
+{
+ explicit StackHeapPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ const auto configDefs = IarewUtils::flagValues(
+ flags, QStringLiteral("--config_def"));
+ for (const auto &configDef : configDefs) {
+ const auto def = configDef.toString();
+ if (def.startsWith(QLatin1String("_CSTACK_SIZE="))) {
+ stackSize = def.split(QLatin1Char('=')).at(1);
+ } else if (def.startsWith(QLatin1String("_HEAP_SIZE="))) {
+ heapSize = def.split(QLatin1Char('=')).at(1);
+ }
+ }
+ }
+
+ QString stackSize;
+ QString heapSize;
+};
+
+} // namespace
+
+// Stm8GeneralSettingsGroup
+
+Stm8GeneralSettingsGroup::Stm8GeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ Q_UNUSED(qbsProductDeps)
+
+ setName(QByteArrayLiteral("General"));
+ setArchiveVersion(kGeneralArchiveVersion);
+ setDataVersion(kGeneralDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildTargetPage(qbsProduct);
+ buildOutputPage(buildRootDirectory, qbsProduct);
+ buildLibraryConfigPage(buildRootDirectory, qbsProduct);
+ buildLibraryOptionsPage(qbsProduct);
+ buildStackHeapPage(qbsProduct);
+}
+
+void Stm8GeneralSettingsGroup::buildTargetPage(
+ const ProductData &qbsProduct)
+{
+ const TargetPageOptions opts(qbsProduct);
+ // Add 'GenCodeModel' item
+ // (Code model: small/medium/large).
+ addOptionsGroup(QByteArrayLiteral("GenCodeModel"),
+ {}, {opts.codeModel});
+ // Add 'GenDataModel' item
+ // (Data model: small/medium/large).
+ addOptionsGroup(QByteArrayLiteral("GenDataModel"),
+ {}, {opts.dataModel});
+}
+
+void Stm8GeneralSettingsGroup::buildOutputPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GOutputBinary' item (Output file: executable/library).
+ addOptionsGroup(QByteArrayLiteral("GOutputBinary"),
+ {}, {opts.binaryType});
+ // Add 'ExePath' item (Executable/binaries output directory).
+ addOptionsGroup(QByteArrayLiteral("ExePath"),
+ {}, {opts.binaryDirectory});
+ // Add 'ObjPath' item (Object files output directory).
+ addOptionsGroup(QByteArrayLiteral("ObjPath"),
+ {}, {opts.objectDirectory});
+ // Add 'ListPath' item (List files output directory).
+ addOptionsGroup(QByteArrayLiteral("ListPath"),
+ {}, {opts.listingDirectory});
+}
+
+void Stm8GeneralSettingsGroup::buildLibraryConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ const LibraryConfigPageOptions opts(baseDirectory, qbsProduct);
+ // Add 'GenRuntimeLibSelect' and 'GenRuntimeLibSelectSlave' items
+ // (Link with runtime: none/normal/full/custom).
+ addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelect"),
+ {}, {opts.libraryType});
+ addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelectSlave"),
+ {}, {opts.libraryType});
+ // Add 'GenRTConfigPath' item (Runtime configuration file).
+ addOptionsGroup(QByteArrayLiteral("GenRTConfigPath"),
+ {}, {opts.configPath});
+}
+
+void Stm8GeneralSettingsGroup::buildLibraryOptionsPage(
+ const ProductData &qbsProduct)
+{
+ const LibraryOptionsPageOptions opts(qbsProduct);
+ // Add 'GenLibOutFormatter' item (Printf formatter).
+ addOptionsGroup(QByteArrayLiteral("GenLibOutFormatter"),
+ {}, {opts.printfFormatter});
+ // Add 'GenLibInFormatter' item (Scanf formatter).
+ addOptionsGroup(QByteArrayLiteral("GenLibInFormatter"),
+ {}, {opts.scanfFormatter});
+}
+
+void Stm8GeneralSettingsGroup::buildStackHeapPage(
+ const ProductData &qbsProduct)
+{
+ const StackHeapPageOptions opts(qbsProduct);
+ // Add 'GenStackSize' item (Stack size).
+ addOptionsGroup(QByteArrayLiteral("GenStackSize"),
+ {}, {opts.stackSize});
+ // Add 'GenHeapSize' item (Heap size).
+ addOptionsGroup(QByteArrayLiteral("GenHeapSize"),
+ {}, {opts.heapSize});
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h
new file mode 100644
index 000000000..20def0fd5
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H
+#define QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8GeneralSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Stm8GeneralSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildTargetPage(const ProductData &qbsProduct);
+ void buildOutputPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildLibraryConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildLibraryOptionsPage(const ProductData &qbsProduct);
+ void buildStackHeapPage(const ProductData &qbsProduct);
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp
new file mode 100644
index 000000000..dc74587d4
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "stm8linkersettingsgroup_v3.h"
+
+#include "../../iarewutils.h"
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+constexpr int kLinkerArchiveVersion = 5;
+constexpr int kLinkerDataVersion = 4;
+
+namespace {
+
+// Config page options.
+
+struct ConfigPageOptions final
+{
+ explicit ConfigPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+
+ // Enumerate all product linker config files
+ // (which are set trough 'linkerscript' tag).
+ const auto qbsGroups = qbsProduct.groups();
+ for (const auto &qbsGroup : qbsGroups) {
+ const auto qbsArtifacts = qbsGroup.sourceArtifacts();
+ for (const auto &qbsArtifact : qbsArtifacts) {
+ const auto qbsTags = qbsArtifact.fileTags();
+ if (!qbsTags.contains(QLatin1String("linkerscript")))
+ continue;
+ const QString fullConfigPath = qbsArtifact.filePath();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ configFilePaths.push_back(path);
+ }
+ }
+ }
+
+ // Enumerate all product linker config files
+ // (which are set trough '-config' option).
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+ const QVariantList configPathValues = IarewUtils::flagValues(
+ flags, QStringLiteral("--config"));
+ for (const QVariant &configPathValue : configPathValues) {
+ const QString fullConfigPath = configPathValue.toString();
+ if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullConfigPath);
+ if (!configFilePaths.contains(path))
+ configFilePaths.push_back(path);
+ }
+ }
+
+ // Enumerate all config definition symbols (except
+ // the CSTACK_SIZE and HEAP_SIZE which are handles
+ // on the general page).
+ configDefinitions = IarewUtils::flagValues(
+ flags, QStringLiteral("--config_def"));
+ configDefinitions.erase(std::remove_if(
+ configDefinitions.begin(),
+ configDefinitions.end(),
+ [](const auto &definition){
+ const auto def = definition.toString();
+ return def.startsWith(QLatin1String("_CSTACK_SIZE"))
+ || def.startsWith(QLatin1String("_HEAP_SIZE"));
+ }), configDefinitions.end());
+ }
+
+ QVariantList configFilePaths;
+ QVariantList configDefinitions;
+};
+
+struct LibraryPageOptions final
+{
+ explicit LibraryPageOptions(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct);
+
+ entryPoint = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("entryPoint"));
+
+ // Add static libraries paths.
+ const QStringList staticLibrariesProps =
+ gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ for (const QString &staticLibrary : staticLibrariesProps) {
+ const QFileInfo staticLibraryInfo(staticLibrary);
+ if (staticLibraryInfo.isAbsolute()) {
+ const QString fullStaticLibraryPath =
+ staticLibraryInfo.absoluteFilePath();
+ if (fullStaticLibraryPath.startsWith(toolkitPath,
+ Qt::CaseInsensitive)) {
+ const QString path = IarewUtils::toolkitRelativeFilePath(
+ toolkitPath, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ } else {
+ const QString path = IarewUtils::projectRelativeFilePath(
+ baseDirectory, fullStaticLibraryPath);
+ staticLibraries.push_back(path);
+ }
+ } else {
+ staticLibraries.push_back(staticLibrary);
+ }
+ }
+
+ // Add static libraries from product dependencies.
+ for (const ProductData &qbsProductDep : qbsProductDeps) {
+ const QString depBinaryPath = QLatin1String("$PROJ_DIR$/")
+ + gen::utils::targetBinaryPath(baseDirectory,
+ qbsProductDep);
+ staticLibraries.push_back(depBinaryPath);
+ }
+ }
+
+ QString entryPoint;
+ QVariantList staticLibraries;
+};
+
+struct OptimizationsPageOptions final
+{
+ explicit OptimizationsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+
+ mergeDuplicateSections = flags.contains(
+ QLatin1String("--merge_duplicate_sections"));
+ }
+
+ bool mergeDuplicateSections = 0;
+};
+
+// Output page options.
+
+struct OutputPageOptions final
+{
+ explicit OutputPageOptions(const ProductData &qbsProduct)
+ {
+ outputFile = gen::utils::targetBinary(qbsProduct);
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+
+ enableDebugInfo = !flags.contains(QLatin1String("--strip"));
+ }
+
+ QString outputFile;
+ bool enableDebugInfo = 1;
+};
+
+// List page options.
+
+struct ListPageOptions final
+{
+ enum ListingAction {
+ NoListing,
+ GenerateListing
+ };
+
+ explicit ListPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ generateMap = gen::utils::cppBooleanModuleProperty(
+ qbsProps, QStringLiteral("generateMapFile"))
+ ? ListPageOptions::GenerateListing
+ : ListPageOptions::NoListing;
+ }
+
+ ListingAction generateMap = NoListing;
+};
+
+// Define page options.
+
+struct DefinePageOptions final
+{
+ explicit DefinePageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps);
+
+ defineSymbols = IarewUtils::flagValues(
+ flags, QStringLiteral("--define_symbol"));
+ }
+
+ QVariantList defineSymbols;
+};
+
+// Diagnostics page options.
+
+struct DiagnosticsPageOptions final
+{
+ explicit DiagnosticsPageOptions(const ProductData &qbsProduct)
+ {
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ warningsAsErrors = gen::utils::cppIntegerModuleProperty(
+ qbsProps, QStringLiteral("treatWarningsAsErrors"));
+ }
+
+ int warningsAsErrors = 0;
+};
+
+} // namespace
+
+// Stm8LinkerSettingsGroup
+
+Stm8LinkerSettingsGroup::Stm8LinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ setName(QByteArrayLiteral("ILINK"));
+ setArchiveVersion(kLinkerArchiveVersion);
+ setDataVersion(kLinkerDataVersion);
+ setDataDebugInfo(gen::utils::debugInformation(qbsProduct));
+
+ const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject);
+
+ buildConfigPage(buildRootDirectory, qbsProduct);
+ buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps);
+ buildOptimizationsPage(qbsProduct);
+ buildOutputPage(qbsProduct);
+ buildListPage(qbsProduct);
+ buildDefinePage(qbsProduct);
+ buildDiagnosticsPage(qbsProduct);
+
+ // Should be called as latest stage!
+ buildExtraOptionsPage(qbsProduct);
+}
+
+void Stm8LinkerSettingsGroup::buildConfigPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct)
+{
+ ConfigPageOptions opts(baseDirectory, qbsProduct);
+
+ if (opts.configFilePaths.count() > 0) {
+ // Note: IAR IDE does not allow to specify a multiple config files,
+ // although the IAR linker support it. So, we use followig 'trick':
+ // we take a first config file and to add it as usual to required items;
+ // and then an other remainders we forward to the "Extra options page".
+ const QVariant configPath = opts.configFilePaths.takeFirst();
+ // Add 'IlinkIcfOverride' item (Override default).
+ addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"),
+ {}, {1});
+ // Add 'IlinkIcfFile' item (Linke configuration file).
+ addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"),
+ {}, {configPath});
+
+ // Add remainder configuration files to the "Extra options page".
+ if (!opts.configFilePaths.isEmpty()) {
+ for (QVariant &configPath : opts.configFilePaths)
+ configPath = QLatin1String("--config ") + configPath.toString();
+
+ m_extraOptions << opts.configFilePaths;
+ }
+ }
+
+ // Add 'IlinkConfigDefines' item (Configuration file
+ // symbol definitions).
+ addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"),
+ {}, opts.configDefinitions);
+}
+
+void Stm8LinkerSettingsGroup::buildLibraryPage(
+ const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+{
+ LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps);
+
+ // Add 'IlinkOverrideProgramEntryLabel' item
+ // (Override default program entry).
+ addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"),
+ {}, {1});
+
+ if (opts.entryPoint.isEmpty()) {
+ // Add 'IlinkProgramEntryLabelSelect' item
+ // (Defined by application).
+ addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"),
+ {}, {1});
+ } else {
+ // Add 'IlinkProgramEntryLabel' item
+ // (Entry symbol).
+ addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"),
+ {}, {opts.entryPoint});
+ }
+
+ // Add 'IlinkAdditionalLibs' item (Additional libraries).
+ addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"),
+ {}, {opts.staticLibraries});
+}
+
+void Stm8LinkerSettingsGroup::buildOptimizationsPage(
+ const ProductData &qbsProduct)
+{
+ OptimizationsPageOptions opts(qbsProduct);
+
+ // Add 'IlinkOptMergeDuplSections' item
+ // (Merge duplicate sections).
+ addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"),
+ {}, {opts.mergeDuplicateSections});
+}
+
+void Stm8LinkerSettingsGroup::buildOutputPage(
+ const ProductData &qbsProduct)
+{
+ const OutputPageOptions opts(qbsProduct);
+
+ // Add 'IlinkOutputFile' item (Output file name).
+ addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"),
+ {}, {opts.outputFile});
+ // Add 'IlinkDebugInfoEnable' item
+ // (Include debug information in output).
+ addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"),
+ {}, {opts.enableDebugInfo});
+}
+
+void Stm8LinkerSettingsGroup::buildListPage(
+ const ProductData &qbsProduct)
+{
+ const ListPageOptions opts(qbsProduct);
+ // Add 'IlinkMapFile' item (Generate linker map file).
+ addOptionsGroup(QByteArrayLiteral("IlinkMapFile"),
+ {}, {opts.generateMap});
+}
+
+void Stm8LinkerSettingsGroup::buildDefinePage(
+ const ProductData &qbsProduct)
+{
+ const DefinePageOptions opts(qbsProduct);
+ // Add 'IlinkDefines' item (Defined symbols).
+ addOptionsGroup(QByteArrayLiteral("IlinkDefines"),
+ {}, opts.defineSymbols);
+}
+
+void Stm8LinkerSettingsGroup::buildDiagnosticsPage(
+ const ProductData &qbsProduct)
+{
+ const DiagnosticsPageOptions opts(qbsProduct);
+ // Add 'IlinkWarningsAreErrors' item (Treat all warnings as errors).
+ addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"),
+ {}, {opts.warningsAsErrors});
+}
+
+void Stm8LinkerSettingsGroup::buildExtraOptionsPage(
+ const ProductData &qbsProduct)
+{
+ Q_UNUSED(qbsProduct)
+
+ if (m_extraOptions.isEmpty())
+ return;
+
+ // Add 'IlinkUseExtraOptions' (Use command line options).
+ addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"),
+ {}, {1});
+ // Add 'IlinkExtraOptions' item (Command line options).
+ addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"),
+ {}, m_extraOptions);
+}
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h
new file mode 100644
index 000000000..b214ebe35
--- /dev/null
+++ b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H
+#define QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H
+
+#include "../../iarewsettingspropertygroup.h"
+
+namespace qbs {
+namespace iarew {
+namespace stm8 {
+namespace v3 {
+
+class Stm8LinkerSettingsGroup final : public IarewSettingsPropertyGroup
+{
+public:
+ explicit Stm8LinkerSettingsGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+
+private:
+ void buildConfigPage(const QString &baseDirectory,
+ const ProductData &qbsProduct);
+ void buildLibraryPage(const QString &baseDirectory,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps);
+ void buildOptimizationsPage(const ProductData &qbsProduct);
+
+
+
+ void buildOutputPage(const ProductData &qbsProduct);
+ void buildListPage(const ProductData &qbsProduct);
+ void buildDefinePage(const ProductData &qbsProduct);
+ void buildDiagnosticsPage(const ProductData &qbsProduct);
+ void buildExtraOptionsPage(const ProductData &qbsProduct);
+
+ QVariantList m_extraOptions;
+};
+
+} // namespace v3
+} // namespace stm8
+} // namespace iarew
+} // namespace qbs
+
+#endif // QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H
diff --git a/src/plugins/generator/iarew/iarew.pro b/src/plugins/generator/iarew/iarew.pro
new file mode 100644
index 000000000..d931f365f
--- /dev/null
+++ b/src/plugins/generator/iarew/iarew.pro
@@ -0,0 +1,115 @@
+include(../../plugins.pri)
+include(../../../shared/json/json.pri)
+
+TARGET = iarewgenerator
+
+QT = core
+
+# Plugin file.
+
+SOURCES += \
+ $$PWD/iarewgeneratorplugin.cpp \
+
+# Common files.
+
+HEADERS += \
+ $$PWD/iarewfileversionproperty.h \
+ $$PWD/iarewgenerator.h \
+ $$PWD/iarewoptionpropertygroup.h \
+ $$PWD/iarewproject.h \
+ $$PWD/iarewprojectwriter.h \
+ $$PWD/iarewsettingspropertygroup.h \
+ $$PWD/iarewsourcefilepropertygroup.h \
+ $$PWD/iarewsourcefilespropertygroup.h \
+ $$PWD/iarewtoolchainpropertygroup.h \
+ $$PWD/iarewutils.h \
+ $$PWD/iarewversioninfo.h \
+ $$PWD/iarewworkspace.h \
+ $$PWD/iarewworkspacewriter.h
+
+SOURCES += \
+ $$PWD/iarewfileversionproperty.cpp \
+ $$PWD/iarewgenerator.cpp \
+ $$PWD/iarewoptionpropertygroup.cpp \
+ $$PWD/iarewproject.cpp \
+ $$PWD/iarewprojectwriter.cpp \
+ $$PWD/iarewsettingspropertygroup.cpp \
+ $$PWD/iarewsourcefilepropertygroup.cpp \
+ $$PWD/iarewsourcefilespropertygroup.cpp \
+ $$PWD/iarewtoolchainpropertygroup.cpp \
+ $$PWD/iarewutils.cpp \
+ $$PWD/iarewversioninfo.cpp \
+ $$PWD/iarewworkspace.cpp \
+ $$PWD/iarewworkspacewriter.cpp
+
+# For ARM architecture.
+
+HEADERS += \
+ $$PWD/archs/arm/armarchiversettingsgroup_v8.h \
+ $$PWD/archs/arm/armassemblersettingsgroup_v8.h \
+ $$PWD/archs/arm/armbuildconfigurationgroup_v8.h \
+ $$PWD/archs/arm/armcompilersettingsgroup_v8.h \
+ $$PWD/archs/arm/armgeneralsettingsgroup_v8.h \
+ $$PWD/archs/arm/armlinkersettingsgroup_v8.h
+
+SOURCES += \
+ $$PWD/archs/arm/armarchiversettingsgroup_v8.cpp \
+ $$PWD/archs/arm/armassemblersettingsgroup_v8.cpp \
+ $$PWD/archs/arm/armbuildconfigurationgroup_v8.cpp \
+ $$PWD/archs/arm/armcompilersettingsgroup_v8.cpp \
+ $$PWD/archs/arm/armgeneralsettingsgroup_v8.cpp \
+ $$PWD/archs/arm/armlinkersettingsgroup_v8.cpp
+
+# For AVR architecture.
+
+HEADERS += \
+ $$PWD/archs/avr/avrarchiversettingsgroup_v7.h \
+ $$PWD/archs/avr/avrassemblersettingsgroup_v7.h \
+ $$PWD/archs/avr/avrbuildconfigurationgroup_v7.h \
+ $$PWD/archs/avr/avrcompilersettingsgroup_v7.h \
+ $$PWD/archs/avr/avrgeneralsettingsgroup_v7.h \
+ $$PWD/archs/avr/avrlinkersettingsgroup_v7.h
+
+SOURCES += \
+ $$PWD/archs/avr/avrarchiversettingsgroup_v7.cpp \
+ $$PWD/archs/avr/avrassemblersettingsgroup_v7.cpp \
+ $$PWD/archs/avr/avrbuildconfigurationgroup_v7.cpp \
+ $$PWD/archs/avr/avrcompilersettingsgroup_v7.cpp \
+ $$PWD/archs/avr/avrgeneralsettingsgroup_v7.cpp \
+ $$PWD/archs/avr/avrlinkersettingsgroup_v7.cpp
+
+# For MCS51 architecture.
+
+HEADERS += \
+ $$PWD/archs/mcs51/mcs51archiversettingsgroup_v10.h \
+ $$PWD/archs/mcs51/mcs51assemblersettingsgroup_v10.h \
+ $$PWD/archs/mcs51/mcs51buildconfigurationgroup_v10.h \
+ $$PWD/archs/mcs51/mcs51compilersettingsgroup_v10.h \
+ $$PWD/archs/mcs51/mcs51generalsettingsgroup_v10.h \
+ $$PWD/archs/mcs51/mcs51linkersettingsgroup_v10.h
+
+SOURCES += \
+ $$PWD/archs/mcs51/mcs51archiversettingsgroup_v10.cpp \
+ $$PWD/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp \
+ $$PWD/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp \
+ $$PWD/archs/mcs51/mcs51compilersettingsgroup_v10.cpp \
+ $$PWD/archs/mcs51/mcs51generalsettingsgroup_v10.cpp \
+ $$PWD/archs/mcs51/mcs51linkersettingsgroup_v10.cpp
+
+# For STM8 architecture.
+
+HEADERS += \
+ $$PWD/archs/stm8/stm8archiversettingsgroup_v3.h \
+ $$PWD/archs/stm8/stm8assemblersettingsgroup_v3.h \
+ $$PWD/archs/stm8/stm8buildconfigurationgroup_v3.h \
+ $$PWD/archs/stm8/stm8compilersettingsgroup_v3.h \
+ $$PWD/archs/stm8/stm8generalsettingsgroup_v3.h \
+ $$PWD/archs/stm8/stm8linkersettingsgroup_v3.h
+
+SOURCES += \
+ $$PWD/archs/stm8/stm8archiversettingsgroup_v3.cpp \
+ $$PWD/archs/stm8/stm8assemblersettingsgroup_v3.cpp \
+ $$PWD/archs/stm8/stm8buildconfigurationgroup_v3.cpp \
+ $$PWD/archs/stm8/stm8compilersettingsgroup_v3.cpp \
+ $$PWD/archs/stm8/stm8generalsettingsgroup_v3.cpp \
+ $$PWD/archs/stm8/stm8linkersettingsgroup_v3.cpp
diff --git a/src/plugins/generator/iarew/iarew.qbs b/src/plugins/generator/iarew/iarew.qbs
new file mode 100644
index 000000000..bfa2093fa
--- /dev/null
+++ b/src/plugins/generator/iarew/iarew.qbs
@@ -0,0 +1,114 @@
+import qbs
+import "../../qbsplugin.qbs" as QbsPlugin
+
+QbsPlugin {
+ Depends { name: "qbsjson" }
+
+ name: "iarewgenerator"
+
+ files: ["iarewgeneratorplugin.cpp"]
+
+ Group {
+ name: "IAR EW generator common"
+ files: [
+ "iarewfileversionproperty.cpp",
+ "iarewfileversionproperty.h",
+ "iarewgenerator.cpp",
+ "iarewgenerator.h",
+ "iarewoptionpropertygroup.cpp",
+ "iarewoptionpropertygroup.h",
+ "iarewproject.cpp",
+ "iarewproject.h",
+ "iarewprojectwriter.cpp",
+ "iarewprojectwriter.h",
+ "iarewsettingspropertygroup.cpp",
+ "iarewsettingspropertygroup.h",
+ "iarewsourcefilepropertygroup.cpp",
+ "iarewsourcefilepropertygroup.h",
+ "iarewsourcefilespropertygroup.cpp",
+ "iarewsourcefilespropertygroup.h",
+ "iarewtoolchainpropertygroup.cpp",
+ "iarewtoolchainpropertygroup.h",
+ "iarewutils.cpp",
+ "iarewutils.h",
+ "iarewversioninfo.cpp",
+ "iarewversioninfo.h",
+ "iarewworkspace.cpp",
+ "iarewworkspace.h",
+ "iarewworkspacewriter.cpp",
+ "iarewworkspacewriter.h",
+ ]
+ }
+ Group {
+ name: "IAR EW generator for ARM"
+ prefix: "archs/arm/"
+ files: [
+ "armarchiversettingsgroup_v8.cpp",
+ "armarchiversettingsgroup_v8.h",
+ "armassemblersettingsgroup_v8.cpp",
+ "armassemblersettingsgroup_v8.h",
+ "armbuildconfigurationgroup_v8.cpp",
+ "armbuildconfigurationgroup_v8.h",
+ "armcompilersettingsgroup_v8.cpp",
+ "armcompilersettingsgroup_v8.h",
+ "armgeneralsettingsgroup_v8.cpp",
+ "armgeneralsettingsgroup_v8.h",
+ "armlinkersettingsgroup_v8.cpp",
+ "armlinkersettingsgroup_v8.h",
+ ]
+ }
+ Group {
+ name: "IAR EW generator for AVR"
+ prefix: "archs/avr/"
+ files: [
+ "avrarchiversettingsgroup_v7.cpp",
+ "avrarchiversettingsgroup_v7.h",
+ "avrassemblersettingsgroup_v7.cpp",
+ "avrassemblersettingsgroup_v7.h",
+ "avrbuildconfigurationgroup_v7.cpp",
+ "avrbuildconfigurationgroup_v7.h",
+ "avrcompilersettingsgroup_v7.cpp",
+ "avrcompilersettingsgroup_v7.h",
+ "avrgeneralsettingsgroup_v7.cpp",
+ "avrgeneralsettingsgroup_v7.h",
+ "avrlinkersettingsgroup_v7.cpp",
+ "avrlinkersettingsgroup_v7.h",
+ ]
+ }
+ Group {
+ name: "IAR EW generator for MCS51"
+ prefix: "archs/mcs51/"
+ files: [
+ "mcs51archiversettingsgroup_v10.cpp",
+ "mcs51archiversettingsgroup_v10.h",
+ "mcs51assemblersettingsgroup_v10.cpp",
+ "mcs51assemblersettingsgroup_v10.h",
+ "mcs51buildconfigurationgroup_v10.cpp",
+ "mcs51buildconfigurationgroup_v10.h",
+ "mcs51compilersettingsgroup_v10.cpp",
+ "mcs51compilersettingsgroup_v10.h",
+ "mcs51generalsettingsgroup_v10.cpp",
+ "mcs51generalsettingsgroup_v10.h",
+ "mcs51linkersettingsgroup_v10.cpp",
+ "mcs51linkersettingsgroup_v10.h",
+ ]
+ }
+ Group {
+ name: "IAR EW generator for STM8"
+ prefix: "archs/stm8/"
+ files: [
+ "stm8archiversettingsgroup_v3.cpp",
+ "stm8archiversettingsgroup_v3.h",
+ "stm8assemblersettingsgroup_v3.cpp",
+ "stm8assemblersettingsgroup_v3.h",
+ "stm8buildconfigurationgroup_v3.cpp",
+ "stm8buildconfigurationgroup_v3.h",
+ "stm8compilersettingsgroup_v3.cpp",
+ "stm8compilersettingsgroup_v3.h",
+ "stm8generalsettingsgroup_v3.cpp",
+ "stm8generalsettingsgroup_v3.h",
+ "stm8linkersettingsgroup_v3.cpp",
+ "stm8linkersettingsgroup_v3.h",
+ ]
+ }
+}
diff --git a/src/plugins/generator/iarew/iarewfileversionproperty.cpp b/src/plugins/generator/iarew/iarewfileversionproperty.cpp
new file mode 100644
index 000000000..86790cdf1
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewfileversionproperty.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewfileversionproperty.h"
+#include "iarewversioninfo.h"
+
+namespace qbs {
+
+static QByteArray buildFileVersion(const IarewVersionInfo &versionInfo)
+{
+ switch (versionInfo.marketingVersion()) {
+ case 8:
+ return QByteArrayLiteral('3');
+ default:
+ return {};
+ }
+}
+
+IarewFileVersionProperty::IarewFileVersionProperty(
+ const IarewVersionInfo &versionInfo)
+{
+ setName(QByteArrayLiteral("fileVersion"));
+ const QByteArray fileVersion = buildFileVersion(versionInfo);
+ setValue(fileVersion);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewfileversionproperty.h b/src/plugins/generator/iarew/iarewfileversionproperty.h
new file mode 100644
index 000000000..d377979fa
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewfileversionproperty.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWFILEVERSIONPROPERTY_H
+#define QBS_IAREWFILEVERSIONPROPERTY_H
+
+#include <generators/xmlproperty.h>
+
+namespace qbs {
+
+class IarewVersionInfo;
+
+class IarewFileVersionProperty final : public gen::xml::Property
+{
+public:
+ explicit IarewFileVersionProperty(
+ const IarewVersionInfo &versionInfo);
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWFILEVERSIONPROPERTY_H
diff --git a/src/plugins/generator/iarew/iarewgenerator.cpp b/src/plugins/generator/iarew/iarewgenerator.cpp
new file mode 100644
index 000000000..e6b308182
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewgenerator.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewgenerator.h"
+#include "iarewproject.h"
+#include "iarewprojectwriter.h"
+#include "iarewworkspace.h"
+#include "iarewworkspacewriter.h"
+
+#include <generators/generatableprojectiterator.h>
+
+#include <logging/logger.h>
+#include <logging/translator.h>
+
+#include <tools/filesaver.h>
+
+namespace qbs {
+
+static QString targetFilePath(const QString &baseName,
+ const QString &baseBuildDirectory)
+{
+ return QDir(baseBuildDirectory).absoluteFilePath(
+ baseName + QStringLiteral(".ewp"));
+}
+
+static QString targetFilePath(const GeneratableProductData &product,
+ const QString &baseBuildDirectory)
+{
+ return targetFilePath(product.name(), baseBuildDirectory);
+}
+
+static void writeProjectFiles(const std::map<QString,
+ std::shared_ptr<IarewProject>> &projects,
+ const Internal::Logger &logger)
+{
+ for (const auto &item : projects) {
+ const QString projectFilePath = item.first;
+ Internal::FileSaver file(projectFilePath.toStdString());
+ if (!file.open())
+ throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing")
+ .arg(projectFilePath));
+
+ std::shared_ptr<IarewProject> project = item.second;
+ IarewProjectWriter writer(file.device());
+ if (!(writer.write(project.get()) && file.commit()))
+ throw ErrorInfo(Internal::Tr::tr("Failed to generate %1")
+ .arg(projectFilePath));
+
+ logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg(
+ QFileInfo(projectFilePath).fileName());
+ }
+}
+
+static void writeWorkspace(const std::shared_ptr<IarewWorkspace> &wokspace,
+ const QString &workspaceFilePath,
+ const Internal::Logger &logger)
+{
+ Internal::FileSaver file(workspaceFilePath.toStdString());
+ if (!file.open())
+ throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing")
+ .arg(workspaceFilePath));
+
+ IarewWorkspaceWriter writer(file.device());
+ if (!(writer.write(wokspace.get()) && file.commit()))
+ throw ErrorInfo(Internal::Tr::tr("Failed to generate %1")
+ .arg(workspaceFilePath));
+
+ logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg(
+ QFileInfo(workspaceFilePath).fileName());
+}
+
+IarewGenerator::IarewGenerator(const IarewVersionInfo &versionInfo)
+ : m_versionInfo(versionInfo)
+{
+}
+
+QString IarewGenerator::generatorName() const
+{
+ return QStringLiteral("iarew%1").arg(m_versionInfo.marketingVersion());
+}
+
+void IarewGenerator::reset()
+{
+ m_workspace.reset();
+ m_workspaceFilePath.clear();
+ m_projects.clear();
+}
+
+void IarewGenerator::generate()
+{
+ GeneratableProjectIterator it(project());
+ it.accept(this);
+
+ writeProjectFiles(m_projects, logger());
+ writeWorkspace(m_workspace, m_workspaceFilePath, logger());
+
+ reset();
+}
+
+void IarewGenerator::visitProject(const GeneratableProject &project)
+{
+ const QDir buildDir = project.baseBuildDirectory();
+
+ m_workspaceFilePath = buildDir.absoluteFilePath(
+ project.name() + QStringLiteral(".eww"));
+ m_workspace = std::make_shared<IarewWorkspace>(m_workspaceFilePath);
+}
+
+void IarewGenerator::visitProjectData(const GeneratableProject &project,
+ const GeneratableProjectData &projectData)
+{
+ Q_UNUSED(project)
+ Q_UNUSED(projectData)
+}
+
+void IarewGenerator::visitProduct(const GeneratableProject &project,
+ const GeneratableProjectData &projectData,
+ const GeneratableProductData &productData)
+{
+ Q_UNUSED(projectData);
+ const QString projectFilePath = targetFilePath(
+ productData, project.baseBuildDirectory().absolutePath());
+ const auto targetProject = std::make_shared<IarewProject>(
+ project, productData,
+ m_versionInfo);
+
+ m_projects.insert({projectFilePath, targetProject});
+ m_workspace->addProject(projectFilePath);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewgenerator.h b/src/plugins/generator/iarew/iarewgenerator.h
new file mode 100644
index 000000000..f8c1298f0
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewgenerator.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWGENERATOR_H
+#define QBS_IAREWGENERATOR_H
+
+#include "iarewversioninfo.h"
+
+#include <generators/generator.h>
+#include <generators/igeneratableprojectvisitor.h>
+
+namespace qbs {
+
+class IarewProject;
+class IarewWorkspace;
+
+class IarewGenerator final : public ProjectGenerator, private IGeneratableProjectVisitor
+{
+public:
+ explicit IarewGenerator(const IarewVersionInfo &versionInfo);
+
+ QString generatorName() const final;
+ void generate() final;
+
+private:
+ void reset();
+
+ void visitProject(const GeneratableProject &project) final;
+ void visitProjectData(const GeneratableProject &project,
+ const GeneratableProjectData &projectData) final;
+ void visitProduct(const GeneratableProject &project,
+ const GeneratableProjectData &projectData,
+ const GeneratableProductData &productData) final;
+
+ const IarewVersionInfo m_versionInfo;
+ std::shared_ptr<IarewWorkspace> m_workspace;
+ QString m_workspaceFilePath;
+ std::map<QString, std::shared_ptr<IarewProject>> m_projects;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWGENERATOR_H
diff --git a/src/plugins/generator/iarew/iarewgeneratorplugin.cpp b/src/plugins/generator/iarew/iarewgeneratorplugin.cpp
new file mode 100644
index 000000000..9f0798573
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewgeneratorplugin.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iarewgenerator.h"
+#include "iarewversioninfo.h"
+
+#include <tools/projectgeneratormanager.h>
+#include <tools/qbspluginmanager.h>
+
+static void QbsIarewGeneratorPluginLoad()
+{
+ for (const auto &info : qbs::IarewVersionInfo::knownVersions()) {
+ qbs::ProjectGeneratorManager::registerGenerator(
+ std::make_shared<qbs::IarewGenerator>(info));
+ }
+}
+
+static void QbsIarewGeneratorPluginUnload()
+{
+}
+
+#ifndef GENERATOR_EXPORT
+#if defined(WIN32) || defined(_WIN32)
+#define GENERATOR_EXPORT __declspec(dllexport)
+#else
+#define GENERATOR_EXPORT __attribute__((visibility("default")))
+#endif
+#endif
+
+QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsIarewGeneratorPlugin,
+ QbsIarewGeneratorPluginLoad, QbsIarewGeneratorPluginUnload)
diff --git a/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp b/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp
new file mode 100644
index 000000000..86f12016b
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewoptionpropertygroup.h"
+
+namespace qbs {
+
+IarewOptionPropertyGroup::IarewOptionPropertyGroup(
+ QByteArray name, QVariant version,
+ const QVariantList &states)
+ : gen::xml::PropertyGroup(QByteArrayLiteral("option"))
+{
+ // Append name property item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("name"),
+ std::move(name));
+
+ // Append version property item.
+ if (!version.isNull())
+ appendChild<gen::xml::Property>(QByteArrayLiteral("version"),
+ std::move(version));
+
+ // Append state property items.
+ for (const auto &state : states) {
+ if (state.isNull())
+ continue;
+ appendChild<gen::xml::Property>(QByteArrayLiteral("state"),
+ std::move(state));
+ }
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewoptionpropertygroup.h b/src/plugins/generator/iarew/iarewoptionpropertygroup.h
new file mode 100644
index 000000000..272ee57e4
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewoptionpropertygroup.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWOPTIONPROPERTYGROUP_H
+#define QBS_IAREWOPTIONPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+//#include <QtCore/qvariant.h>
+
+namespace qbs {
+
+class IarewOptionPropertyGroup final
+ : public gen::xml::PropertyGroup
+{
+public:
+ explicit IarewOptionPropertyGroup(
+ QByteArray name, QVariant version,
+ const QVariantList &states);
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWOPTIONPROPERTYGROUP_H
diff --git a/src/plugins/generator/iarew/iarewproject.cpp b/src/plugins/generator/iarew/iarewproject.cpp
new file mode 100644
index 000000000..17e69fa31
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewproject.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewfileversionproperty.h"
+#include "iarewproject.h"
+#include "iarewsourcefilespropertygroup.h"
+#include "iarewutils.h"
+#include "iarewversioninfo.h"
+
+#include "archs/arm/armbuildconfigurationgroup_v8.h"
+#include "archs/avr/avrbuildconfigurationgroup_v7.h"
+#include "archs/mcs51/mcs51buildconfigurationgroup_v10.h"
+#include "archs/stm8/stm8buildconfigurationgroup_v3.h"
+
+#include <logging/translator.h>
+
+namespace qbs {
+
+IarewProject::IarewProject(const GeneratableProject &genProject,
+ const GeneratableProductData &genProduct,
+ const IarewVersionInfo &versionInfo)
+{
+ Q_ASSERT(genProject.projects.size() == genProject.commandLines.size());
+ Q_ASSERT(genProject.projects.size() == genProduct.data.size());
+
+ // Create available configuration group factories.
+ m_factories.push_back(std::make_unique<
+ iarew::arm::v8::ArmBuildConfigurationGroupFactory>());
+ m_factories.push_back(std::make_unique<
+ iarew::avr::v7::AvrBuildConfigurationGroupFactory>());
+ m_factories.push_back(std::make_unique<
+ iarew::mcs51::v10::Mcs51BuildConfigurationGroupFactory>());
+ m_factories.push_back(std::make_unique<
+ iarew::stm8::v3::Stm8BuildConfigurationGroupFactory>());
+
+ // Construct file version item.
+ appendChild<IarewFileVersionProperty>(versionInfo);
+
+ // Construct all build configurations items.
+ const int configsCount = std::max(genProject.projects.size(),
+ genProduct.data.size());
+ for (auto configIndex = 0; configIndex < configsCount; ++configIndex) {
+ const qbs::Project qbsProject = genProject.projects
+ .values().at(configIndex);
+ const ProductData qbsProduct = genProduct.data.values().at(configIndex);
+ const QString confName = gen::utils::buildConfigurationName(qbsProject);
+ const std::vector<ProductData> qbsProductDeps = gen::utils::dependenciesOf
+ (qbsProduct, genProject, confName);
+
+ const auto arch = gen::utils::architecture(qbsProject);
+ if (arch == gen::utils::Architecture::Unknown)
+ throw ErrorInfo(Internal::Tr::tr("Target architecture is not set,"
+ " please use the 'profile' option"));
+
+ // Construct the build configuration item, which are depend from
+ // the architecture and the version.
+ const auto factoryEnd = m_factories.cend();
+ const auto factoryIt = std::find_if(
+ m_factories.cbegin(), factoryEnd,
+ [arch, versionInfo](const auto &factory) {
+ return factory->canCreate(arch, versionInfo.version());
+ });
+ if (factoryIt == factoryEnd) {
+ throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'"
+ " for IAR EW version %2xxx")
+ .arg(gen::utils::architectureName(arch))
+ .arg(versionInfo.marketingVersion()));
+ }
+ auto configGroup = (*factoryIt)->create(
+ qbsProject, qbsProduct, qbsProductDeps);
+ appendChild(std::move(configGroup));
+ }
+
+ // Construct all file groups items.
+ QMapIterator<QString, qbs::ProductData> dataIt(genProduct.data);
+ while (dataIt.hasNext()) {
+ dataIt.next();
+ const auto groups = dataIt.value().groups();
+ for (const auto &group : groups) {
+ // Ignore disabled groups (e.g. when its condition property is false).
+ if (!group.isEnabled())
+ continue;
+ auto sourceArtifacts = group.sourceArtifacts();
+ // Remove the linker script artifacts.
+ sourceArtifacts.erase(std::remove_if(sourceArtifacts.begin(),
+ sourceArtifacts.end(),
+ [](const auto &artifact){
+ const auto tags = artifact.fileTags();
+ return tags.contains(QLatin1String("linkerscript"));
+ }), sourceArtifacts.end());
+
+ if (sourceArtifacts.isEmpty())
+ continue;
+ appendChild<IarewSourceFilesPropertyGroup>(
+ genProject, group.name(), sourceArtifacts);
+ }
+ }
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewproject.h b/src/plugins/generator/iarew/iarewproject.h
new file mode 100644
index 000000000..567a58c55
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewproject.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWPROJECT_H
+#define QBS_IAREWPROJECT_H
+
+#include <generators/generatordata.h>
+#include <generators/xmlproject.h>
+#include <generators/xmlpropertygroup.h>
+
+#include <memory>
+
+namespace qbs {
+
+class IarewVersionInfo;
+
+class IarewProject final : public gen::xml::Project
+{
+public:
+ explicit IarewProject(const GeneratableProject &genProject,
+ const GeneratableProductData &genProduct,
+ const IarewVersionInfo &versionInfo);
+private:
+ std::vector<std::unique_ptr<gen::xml::PropertyGroupFactory>> m_factories;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWPROJECT_H
diff --git a/src/plugins/generator/iarew/iarewprojectwriter.cpp b/src/plugins/generator/iarew/iarewprojectwriter.cpp
new file mode 100644
index 000000000..a1c912a8c
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewprojectwriter.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewprojectwriter.h"
+
+namespace qbs {
+
+IarewProjectWriter::IarewProjectWriter(std::ostream *device)
+ : gen::xml::ProjectWriter(device)
+{
+}
+
+void IarewProjectWriter::visitStart(const gen::xml::Project *project)
+{
+ Q_UNUSED(project)
+ writer()->writeStartElement(QStringLiteral("project"));
+}
+
+void IarewProjectWriter::visitEnd(const gen::xml::Project *project)
+{
+ Q_UNUSED(project)
+ writer()->writeEndElement();
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewprojectwriter.h b/src/plugins/generator/iarew/iarewprojectwriter.h
new file mode 100644
index 000000000..ae425b29e
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewprojectwriter.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWPROJECTWRITER_H
+#define QBS_IAREWPROJECTWRITER_H
+
+#include <generators/xmlprojectwriter.h>
+
+namespace qbs {
+
+class IarewProjectWriter final : public gen::xml::ProjectWriter
+{
+ Q_DISABLE_COPY(IarewProjectWriter)
+public:
+ explicit IarewProjectWriter(std::ostream *device);
+
+private:
+ void visitStart(const gen::xml::Project *project) final;
+ void visitEnd(const gen::xml::Project *project) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWPROJECTWRITER_H
diff --git a/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp b/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp
new file mode 100644
index 000000000..de6fae45a
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewoptionpropertygroup.h"
+#include "iarewsettingspropertygroup.h"
+
+namespace qbs {
+
+constexpr int kDataWantNonLocalPropertyValue = 1;
+
+IarewSettingsPropertyGroup::IarewSettingsPropertyGroup()
+ : gen::xml::PropertyGroup(QByteArrayLiteral("settings"))
+{
+ // Append name property item.
+ m_nameProperty = appendChild<gen::xml::Property>(
+ QByteArrayLiteral("name"), QVariant{});
+
+ // Append archive version property item.
+ m_archiveVersionProperty = appendChild<gen::xml::Property>(
+ QByteArrayLiteral("archiveVersion"), QVariant{});
+
+ // Append data property group item.
+ m_dataPropertyGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("data"));
+ // Append data version property item.
+ m_dataVersionProperty = m_dataPropertyGroup->appendChild<
+ gen::xml::Property>(
+ QByteArrayLiteral("version"), QVariant{});
+ // Append data want non-local property item.
+ m_dataPropertyGroup->appendChild<gen::xml::Property>(
+ QByteArrayLiteral("wantNonLocal"),
+ kDataWantNonLocalPropertyValue);
+ // Append data debug property item.
+ m_dataDebugProperty = m_dataPropertyGroup->appendChild<
+ gen::xml::Property>(
+ QByteArrayLiteral("debug"), QVariant{});
+}
+
+void IarewSettingsPropertyGroup::setName(QByteArray name)
+{
+ m_nameProperty->setValue(std::move(name));
+}
+
+QByteArray IarewSettingsPropertyGroup::name() const
+{
+ return m_nameProperty->value().toByteArray();
+}
+
+void IarewSettingsPropertyGroup::setArchiveVersion(
+ int archiveVersion)
+{
+ m_archiveVersionProperty->setValue(archiveVersion);
+}
+
+int IarewSettingsPropertyGroup::archiveVersion() const
+{
+ return m_archiveVersionProperty->value().toInt();
+}
+
+void IarewSettingsPropertyGroup::setDataVersion(int dataVersion)
+{
+ m_dataVersionProperty->setValue(dataVersion);
+}
+
+void IarewSettingsPropertyGroup::setDataDebugInfo(int debugInfo)
+{
+ m_dataDebugProperty->setValue(debugInfo);
+}
+
+void IarewSettingsPropertyGroup::addOptionsGroup(
+ QByteArray name,
+ QVariant version,
+ const QVariantList &states)
+{
+ m_dataPropertyGroup->appendChild<IarewOptionPropertyGroup>(
+ std::move(name), std::move(version), states);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewsettingspropertygroup.h b/src/plugins/generator/iarew/iarewsettingspropertygroup.h
new file mode 100644
index 000000000..79de48018
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsettingspropertygroup.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSETTINGSPROPERTYGROUP_H
+#define QBS_IAREWSETTINGSPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+class IarewSettingsPropertyGroup : public gen::xml::PropertyGroup
+{
+public:
+ explicit IarewSettingsPropertyGroup();
+
+ void setName(QByteArray name);
+ QByteArray name() const;
+
+ void setArchiveVersion(int archiveVersion);
+ int archiveVersion() const;
+
+protected:
+ void setDataVersion(int dataVersion);
+ void setDataDebugInfo(int debugInfo);
+
+ void addOptionsGroup(QByteArray name, QVariant version,
+ const QVariantList &states);
+
+private:
+ // Don't delete all this RAW pointers explicitly!
+ gen::xml::Property *m_nameProperty = nullptr;
+ gen::xml::Property *m_archiveVersionProperty = nullptr;
+
+ gen::xml::Property *m_dataPropertyGroup = nullptr;
+ gen::xml::Property *m_dataVersionProperty = nullptr;
+ gen::xml::Property *m_dataDebugProperty = nullptr;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWSETTINGSPROPERTYGROUP_H
diff --git a/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp
new file mode 100644
index 000000000..33c26e8b8
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewsourcefilepropertygroup.h"
+#include "iarewutils.h"
+
+#include <generators/generatordata.h>
+
+#include <tools/stringconstants.h>
+
+namespace qbs {
+
+IarewSourceFilePropertyGroup::IarewSourceFilePropertyGroup(
+ const GeneratableProject &genProject,
+ const ArtifactData &sourceArtifact)
+ : gen::xml::PropertyGroup(QByteArrayLiteral("file"))
+{
+ // Create file path property item.
+ const QString fullFilePath = sourceArtifact.filePath();
+ const QString relativeFilePath = IarewUtils::projectRelativeFilePath(
+ genProject.baseBuildDirectory().absolutePath(),
+ fullFilePath);
+ appendChild<gen::xml::Property>(QByteArrayLiteral("name"),
+ relativeFilePath);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h
new file mode 100644
index 000000000..5f88cec27
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSOURCEFILEPROPERTYGROUP_H
+#define QBS_IAREWSOURCEFILEPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+class ArtifactData;
+class GeneratableProject;
+
+class IarewSourceFilePropertyGroup final
+ : public gen::xml::PropertyGroup
+{
+public:
+ explicit IarewSourceFilePropertyGroup(
+ const GeneratableProject &genProject,
+ const ArtifactData &sourceArtifact);
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWSOURCEFILEPROPERTYGROUP_H
diff --git a/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp
new file mode 100644
index 000000000..adb5925b2
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewsourcefilepropertygroup.h"
+#include "iarewsourcefilespropertygroup.h"
+
+#include <generators/generatordata.h>
+
+#include <tools/stringconstants.h>
+
+namespace qbs {
+
+IarewSourceFilesPropertyGroup::IarewSourceFilesPropertyGroup(
+ const GeneratableProject &genProject,
+ const QString &filesGroupName,
+ const QList<ArtifactData> &sourceFiles)
+ : gen::xml::PropertyGroup(QByteArrayLiteral("group"))
+{
+ // Create group name property item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("name"),
+ filesGroupName);
+
+ // Create file paths property items.
+ for (const auto &sourceFile : sourceFiles)
+ appendChild<IarewSourceFilePropertyGroup>(genProject,
+ sourceFile);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h
new file mode 100644
index 000000000..8d8a4be0c
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWSOURCEFILESPROPERTYGROUP_H
+#define QBS_IAREWSOURCEFILESPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+class IarewSourceFilesPropertyGroup final
+ : public gen::xml::PropertyGroup
+{
+public:
+ explicit IarewSourceFilesPropertyGroup(
+ const GeneratableProject &genProject,
+ const QString &filesGroupName,
+ const QList<ArtifactData> &sourceFiles);
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWSOURCEFILESPROPERTYGROUP_H
diff --git a/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp
new file mode 100644
index 000000000..dba5015bf
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewtoolchainpropertygroup.h"
+
+namespace qbs {
+
+IarewToolchainPropertyGroup::IarewToolchainPropertyGroup(
+ const QByteArray &toolchainName)
+ : gen::xml::PropertyGroup(QByteArrayLiteral("toolchain"))
+{
+ // Append toolchain name property item.
+ appendProperty(QByteArrayLiteral("name"), toolchainName);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h
new file mode 100644
index 000000000..e5bd6f071
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWTOOLCHAINPROPERTYGROUP_H
+#define QBS_IAREWTOOLCHAINPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+class IarewToolchainPropertyGroup final
+ : public gen::xml::PropertyGroup
+{
+public:
+ explicit IarewToolchainPropertyGroup(
+ const QByteArray &toolchainName);
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWTOOLCHAINPROPERTYGROUP_H
diff --git a/src/plugins/generator/iarew/iarewutils.cpp b/src/plugins/generator/iarew/iarewutils.cpp
new file mode 100644
index 000000000..f00fce026
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewutils.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewutils.h"
+
+#include <generators/generatorutils.h>
+
+namespace qbs {
+namespace IarewUtils {
+
+QString toolkitRootPath(const ProductData &qbsProduct)
+{
+ QDir dir(qbsProduct.moduleProperties()
+ .getModuleProperty(Internal::StringConstants::cppModule(),
+ QStringLiteral("toolchainInstallPath"))
+ .toString());
+ dir.cdUp();
+ return dir.absolutePath();
+}
+
+QString dlibToolkitRootPath(const ProductData &qbsProduct)
+{
+ return toolkitRootPath(qbsProduct) + QLatin1String("/lib/dlib");
+}
+
+QString clibToolkitRootPath(const ProductData &qbsProduct)
+{
+ return toolkitRootPath(qbsProduct) + QLatin1String("/lib/clib");
+}
+
+QString libToolkitRootPath(const ProductData &qbsProduct)
+{
+ return toolkitRootPath(qbsProduct) + QLatin1String("/lib");
+}
+
+QString toolkitRelativeFilePath(const QString &basePath,
+ const QString &fullFilePath)
+{
+ return QLatin1String("$TOOLKIT_DIR$/")
+ + gen::utils::relativeFilePath(basePath, fullFilePath);
+}
+
+QString projectRelativeFilePath(const QString &basePath,
+ const QString &fullFilePath)
+{
+ return QLatin1String("$PROJ_DIR$/")
+ + gen::utils::relativeFilePath(basePath, fullFilePath);
+}
+
+OutputBinaryType outputBinaryType(const ProductData &qbsProduct)
+{
+ const auto qbsProductType = qbsProduct.type();
+ if (qbsProductType.contains(QLatin1String("application")))
+ return ApplicationOutputType;
+ if (qbsProductType.contains(QLatin1String("staticlibrary")))
+ return LibraryOutputType;
+ return ApplicationOutputType;
+}
+
+QString flagValue(const QStringList &flags, const QString &flagKey)
+{
+ // Seach for full 'flagKey' option matching.
+ const auto flagBegin = flags.cbegin();
+ const auto flagEnd = flags.cend();
+ auto flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) {
+ return flag == flagKey;
+ });
+ if (flagIt == flagEnd) {
+ // Search for start/end of 'flagKey' matching.
+ flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) {
+ return flag.startsWith(flagKey) || flag.endsWith(flagKey);
+ });
+ if (flagIt == flagEnd)
+ return {};
+ }
+
+ QString value;
+ // Check that option is in form of 'flagKey=<flagValue>'.
+ if (flagIt->contains(QLatin1Char('='))) {
+ value = flagIt->split(QLatin1Char('=')).at(1).trimmed();
+ } else if (flagKey.count() < flagIt->count()) {
+ // In this case an option is in form of 'flagKey<flagValue>'.
+ value = flagIt->mid(flagKey.count()).trimmed();
+ } else {
+ // In this case an option is in form of 'flagKey <flagValue>'.
+ ++flagIt;
+ if (flagIt < flagEnd)
+ value = (*flagIt).trimmed();
+ else
+ return {};
+ }
+ return value;
+}
+
+QVariantList flagValues(const QStringList &flags, const QString &flagKey)
+{
+ QVariantList values;
+ for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) {
+ if (*flagIt != flagKey)
+ continue;
+ ++flagIt;
+ values.push_back(*flagIt);
+ }
+ return values;
+}
+
+QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"),
+ QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"),
+ QStringLiteral("commonCompilerFlags")});
+}
+
+QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("assemblerFlags")});
+}
+
+QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags"),
+ QStringLiteral("driverLinkerFlags")});
+}
+
+} // namespace IarewUtils
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewutils.h b/src/plugins/generator/iarew/iarewutils.h
new file mode 100644
index 000000000..2d32ac188
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewutils.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWUTILS_H
+#define QBS_IAREWUTILS_H
+
+#include <qbs.h>
+
+#include <tools/stringconstants.h>
+
+namespace qbs {
+namespace IarewUtils {
+
+enum OutputBinaryType {
+ ApplicationOutputType,
+ LibraryOutputType
+};
+
+OutputBinaryType outputBinaryType(const ProductData &qbsProduct);
+
+QString toolkitRootPath(const ProductData &qbsProduct);
+
+QString dlibToolkitRootPath(const ProductData &qbsProduct);
+
+QString clibToolkitRootPath(const ProductData &qbsProduct);
+
+QString libToolkitRootPath(const ProductData &qbsProduct);
+
+QString toolkitRelativeFilePath(const QString &basePath,
+ const QString &fullFilePath);
+
+QString projectRelativeFilePath(const QString &basePath,
+ const QString &fullFilePath);
+
+QString flagValue(const QStringList &flags, const QString &flagKey);
+
+QVariantList flagValues(const QStringList &flags, const QString &flagKey);
+
+QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps);
+
+QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps);
+
+QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps);
+
+} // namespace IarewUtils
+} // namespace qbs
+
+#endif // QBS_IAREWUTILS_H
diff --git a/src/plugins/generator/iarew/iarewversioninfo.cpp b/src/plugins/generator/iarew/iarewversioninfo.cpp
new file mode 100644
index 000000000..2fc14d515
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewversioninfo.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iarewversioninfo.h"
+
+#include <QtCore/qdebug.h>
+
+namespace qbs {
+
+IarewVersionInfo::IarewVersionInfo(
+ const Version &version,
+ const std::set<gen::utils::Architecture> &archs)
+ : gen::VersionInfo(version, archs)
+{
+}
+
+std::set<IarewVersionInfo> IarewVersionInfo::knownVersions()
+{
+ static const std::set<IarewVersionInfo> known = {
+ {Version(8), {gen::utils::Architecture::Arm}},
+ {Version(7), {gen::utils::Architecture::Avr}},
+ {Version(10), {gen::utils::Architecture::Mcs51}},
+ {Version(3), {gen::utils::Architecture::Stm8}},
+ };
+ return known;
+}
+
+int IarewVersionInfo::marketingVersion() const
+{
+ const auto mv = gen::VersionInfo::marketingVersion();
+ for (const IarewVersionInfo &known : knownVersions()) {
+ if (known.version().majorVersion() == mv)
+ return mv;
+ }
+ qWarning() << QStringLiteral("Unrecognized IAR EW version: ")
+ << version().toString();
+ return 0;
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewversioninfo.h b/src/plugins/generator/iarew/iarewversioninfo.h
new file mode 100644
index 000000000..4fd1b1fbc
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewversioninfo.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWVERSIONINFO_H
+#define QBS_IAREWVERSIONINFO_H
+
+#include <generators/generatorutils.h>
+#include <generators/generatorversioninfo.h>
+
+namespace qbs {
+
+class IarewVersionInfo final : public gen::VersionInfo
+{
+public:
+ IarewVersionInfo(const Version &version,
+ const std::set<gen::utils::Architecture> &archs);
+
+ int marketingVersion() const final;
+
+ static std::set<IarewVersionInfo> knownVersions();
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWVERSIONINFO_H
diff --git a/src/plugins/generator/iarew/iarewworkspace.cpp b/src/plugins/generator/iarew/iarewworkspace.cpp
new file mode 100644
index 000000000..bfe22aea7
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewworkspace.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iarewworkspace.h"
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+IarewWorkspace::IarewWorkspace(const QString &workspacePath)
+ : gen::xml::Workspace(workspacePath)
+{
+ appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("batchBuild"));
+}
+
+void IarewWorkspace::addProject(const QString &projectFilePath)
+{
+ const QString relativeProjectPath = QLatin1String("$WS_DIR$/")
+ + m_baseDirectory.relativeFilePath(projectFilePath);
+
+ const auto projectGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("project"));
+ projectGroup->appendProperty("path", relativeProjectPath);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewworkspace.h b/src/plugins/generator/iarew/iarewworkspace.h
new file mode 100644
index 000000000..ea14e4174
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewworkspace.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWWORKSPACE_H
+#define QBS_IAREWWORKSPACE_H
+
+#include <generators/xmlworkspace.h>
+
+#include <QtCore/qdir.h>
+
+namespace qbs {
+
+class IarewWorkspace final : public gen::xml::Workspace
+{
+public:
+ explicit IarewWorkspace(const QString &workspacePath);
+ void addProject(const QString &projectPath) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWWORKSPACE_H
diff --git a/src/plugins/generator/iarew/iarewworkspacewriter.cpp b/src/plugins/generator/iarew/iarewworkspacewriter.cpp
new file mode 100644
index 000000000..8b56b7c54
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewworkspacewriter.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "iarewworkspacewriter.h"
+
+namespace qbs {
+
+IarewWorkspaceWriter::IarewWorkspaceWriter(std::ostream *device)
+ : gen::xml::WorkspaceWriter(device)
+{
+}
+
+void IarewWorkspaceWriter::visitStart(const gen::xml::Workspace *workspace)
+{
+ Q_UNUSED(workspace)
+ writer()->writeStartElement(QStringLiteral("workspace"));
+}
+
+void IarewWorkspaceWriter::visitEnd(const gen::xml::Workspace *workspace)
+{
+ Q_UNUSED(workspace)
+ writer()->writeEndElement();
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/iarew/iarewworkspacewriter.h b/src/plugins/generator/iarew/iarewworkspacewriter.h
new file mode 100644
index 000000000..3966744fb
--- /dev/null
+++ b/src/plugins/generator/iarew/iarewworkspacewriter.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_IAREWWORKSPACEWRITER_H
+#define QBS_IAREWWORKSPACEWRITER_H
+
+#include <generators/xmlworkspacewriter.h>
+
+namespace qbs {
+
+class IarewWorkspaceWriter final : public gen::xml::WorkspaceWriter
+{
+ Q_DISABLE_COPY(IarewWorkspaceWriter)
+public:
+ explicit IarewWorkspaceWriter(std::ostream *device);
+
+private:
+ void visitStart(const gen::xml::Workspace *workspace) final;
+ void visitEnd(const gen::xml::Workspace *workspace) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_IAREWWORKSPACEWRITER_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp
new file mode 100644
index 000000000..ce013fba5
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51buildtargetgroup_v5.h"
+#include "mcs51commonpropertygroup_v5.h"
+#include "mcs51debugoptiongroup_v5.h"
+#include "mcs51dlloptiongroup_v5.h"
+#include "mcs51targetcommonoptionsgroup_v5.h"
+#include "mcs51targetgroup_v5.h"
+#include "mcs51utilitiesgroup_v5.h"
+#include "mcs51utils.h"
+
+#include "../../keiluvfilesgroupspropertygroup.h"
+#include "../../keiluvutils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51BuildTargetGroup::Mcs51BuildTargetGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<qbs::ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup("Target")
+{
+ // Append target name item (it is a build configuration name).
+ const QString targetName = gen::utils::buildConfigurationName(
+ qbsProject);
+ appendProperty(QByteArrayLiteral("TargetName"), targetName);
+ // Append toolset number group item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetNumber"),
+ QByteArrayLiteral("0x0"));
+ // Append toolset name group item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetName"),
+ QByteArrayLiteral("MCS-51"));
+
+ // Append target option group item.
+ const auto targetOptionGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("TargetOption"));
+
+ targetOptionGroup->appendChild<Mcs51TargetCommonOptionsGroup>(
+ qbsProject, qbsProduct);
+ targetOptionGroup->appendChild<Mcs51CommonPropertyGroup>(
+ qbsProject, qbsProduct);
+ targetOptionGroup->appendChild<Mcs51DllOptionGroup>(
+ qbsProject, qbsProduct);
+ targetOptionGroup->appendChild<Mcs51DebugOptionGroup>(
+ qbsProject, qbsProduct);
+ targetOptionGroup->appendChild<Mcs51UtilitiesGroup>(
+ qbsProject, qbsProduct);
+ targetOptionGroup->appendChild<Mcs51TargetGroup>(
+ qbsProject, qbsProduct);
+
+ // Append files group.
+ appendChild<KeiluvFilesGroupsPropertyGroup>(qbsProject, qbsProduct,
+ qbsProductDeps);
+}
+
+bool Mcs51BuildTargetGroupFactory::canCreate(
+ gen::utils::Architecture arch,
+ const Version &version) const
+{
+ return arch == gen::utils::Architecture::Mcs51
+ && version.majorVersion() == KeiluvConstants::kUVisionVersion;
+}
+
+std::unique_ptr<gen::xml::PropertyGroup>
+Mcs51BuildTargetGroupFactory::create(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<qbs::ProductData> &qbsProductDeps) const
+{
+ const auto group = new Mcs51BuildTargetGroup(
+ qbsProject, qbsProduct, qbsProductDeps);
+ return std::unique_ptr<Mcs51BuildTargetGroup>(group);
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h
new file mode 100644
index 000000000..ef0c0ccba
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H
+#define QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51BuildTargetGroup final : public gen::xml::PropertyGroup
+{
+private:
+ explicit Mcs51BuildTargetGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<qbs::ProductData> &qbsProductDeps);
+
+ friend class Mcs51BuildTargetGroupFactory;
+};
+
+class Mcs51BuildTargetGroupFactory final
+ : public gen::xml::PropertyGroupFactory
+{
+public:
+ bool canCreate(gen::utils::Architecture arch,
+ const Version &version) const final;
+
+ std::unique_ptr<gen::xml::PropertyGroup> create(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<qbs::ProductData> &qbsProductDeps) const final;
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp
new file mode 100644
index 000000000..3d4d33046
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51commonpropertygroup_v5.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51CommonPropertyGroup::Mcs51CommonPropertyGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("CommonProperty")
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProduct)
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h
new file mode 100644
index 000000000..66dfc7a3e
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H
+#define QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51CommonPropertyGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51CommonPropertyGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_MCS51COMMONPROPERTYGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp
new file mode 100644
index 000000000..2175cc488
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51debugoptiongroup_v5.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51DebugOptionGroup::Mcs51DebugOptionGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("DebugOption")
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProduct)
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h
new file mode 100644
index 000000000..473cf605c
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H
+#define QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51DebugOptionGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51DebugOptionGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp
new file mode 100644
index 000000000..59aec721d
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51dlloptiongroup_v5.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51DllOptionGroup::Mcs51DllOptionGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("DllOption")
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProduct)
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h
new file mode 100644
index 000000000..e16833acc
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H
+#define QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51DllOptionGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51DllOptionGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp
new file mode 100644
index 000000000..8d7257713
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetassemblergroup_v5.h"
+#include "mcs51utils.h"
+
+#include "../../keiluvutils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+namespace {
+
+struct AssemblerPageOptions final
+{
+ explicit AssemblerPageOptions(const Project &qbsProject,
+ const ProductData &qbsProduct)
+ {
+ Q_UNUSED(qbsProject)
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto flags = qbs::KeiluvUtils::cppModuleAssemblerFlags(qbsProps);
+
+ // Don't use standard macro.
+ if (flags.contains(QLatin1String("NOMACRO"), Qt::CaseInsensitive))
+ useStandardMacroProcessor = false;
+
+ // Use MPL.
+ if (flags.contains(QLatin1String("MPL"), Qt::CaseInsensitive))
+ useMacroProcessingLanguage = true;
+
+ // Define 8051 SFR names.
+ if (flags.contains(QLatin1String("NOMOD51"), Qt::CaseInsensitive))
+ suppressSfrNames = true;
+
+ // Define symbols.
+ defineSymbols = qbs::KeiluvUtils::defines(qbsProps);
+ // Include paths.
+ includePaths = qbs::KeiluvUtils::includes(qbsProps);
+
+ // Interpret other assembler flags as a misc controls (exclude only
+ // that flags which are was already handled).
+ for (const auto &flag : flags) {
+ if (flag.compare(QLatin1String("NOMACRO"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("MACRO"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("NOMPL"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("MPL"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("NOMOD51"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("MOD51"),
+ Qt::CaseInsensitive) == 0
+ ) {
+ continue;
+ }
+ miscControls.push_back(flag);
+ }
+ }
+
+ int useStandardMacroProcessor = true;
+ int useMacroProcessingLanguage = false;
+ int suppressSfrNames = false;
+ QStringList defineSymbols;
+ QStringList includePaths;
+ QStringList miscControls;
+};
+
+} // namespace
+
+Mcs51TargetAssemblerGroup::Mcs51TargetAssemblerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("Ax51")
+{
+ const AssemblerPageOptions opts(qbsProject, qbsProduct);
+
+ // Add 'Macro processor (Standard)'
+ appendProperty(QByteArrayLiteral("UseStandard"),
+ opts.useStandardMacroProcessor);
+ // Add 'Macro processor (MPL)'
+ appendProperty(QByteArrayLiteral("UseMpl"),
+ opts.useMacroProcessingLanguage);
+ // Add 'Define 8051 SFR names'
+ appendProperty(QByteArrayLiteral("UseMod51"),
+ opts.suppressSfrNames);
+
+ // Add other various controls.
+ // Note: A sub-items order makes sense!
+ const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("VariousControls"));
+ // Add 'Misc Controls' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("MiscControls"),
+ opts.miscControls, QLatin1Char(' '));
+ // Add 'Define' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("Define"),
+ opts.defineSymbols);
+ // Add an empty 'Undefine' item.
+ variousControlsGroup->appendProperty(
+ QByteArrayLiteral("Undefine"), {});
+ // Add 'Include Paths' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("IncludePath"),
+ opts.includePaths, QLatin1Char(';'));
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h
new file mode 100644
index 000000000..f9a82304d
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3
+#define QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetAssemblerGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetAssemblerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp
new file mode 100644
index 000000000..de1be1ef6
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetcommonoptionsgroup_v5.h"
+
+#include "../../keiluvutils.h"
+
+#include <generators/generatorutils.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+namespace {
+
+struct CommonPageOptions final
+{
+ explicit CommonPageOptions(const Project &qbsProject,
+ const ProductData &qbsProduct)
+ {
+ Q_UNUSED(qbsProject)
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto flags = KeiluvUtils::cppModuleCompilerFlags(qbsProps);
+
+ // Browse information.
+ if (flags.contains(QLatin1String("BROWSE"), Qt::CaseInsensitive))
+ browseInfo = true;
+
+ // Debug information.
+ debugInfo = gen::utils::debugInformation(qbsProduct);
+
+ // Output parameters.
+ executableName = gen::utils::targetBinary(qbsProduct);
+ // Fix output binary name if it is a library. Because
+ // the IDE appends an additional suffix (.LIB) to end
+ // of an output library name.
+ if (executableName.endsWith(QLatin1String(".lib")))
+ executableName = qbsProduct.targetName();
+
+ const QString baseDirectory = gen::utils::buildRootPath(qbsProject);
+ objectDirectory = QDir::toNativeSeparators(
+ gen::utils::objectsOutputDirectory(
+ baseDirectory, qbsProduct));
+ listingDirectory = QDir::toNativeSeparators(
+ gen::utils::listingOutputDirectory(
+ baseDirectory, qbsProduct));
+
+ // Target type.
+ targetType = KeiluvUtils::outputBinaryType(qbsProduct);
+ }
+
+ int browseInfo = false;
+ int debugInfo = false;
+ QString executableName;
+ QString objectDirectory;
+ QString listingDirectory;
+ KeiluvUtils::OutputBinaryType targetType =
+ KeiluvUtils::ApplicationOutputType;
+};
+
+} // namespace
+
+Mcs51TargetCommonOptionsGroup::Mcs51TargetCommonOptionsGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("TargetCommonOption")
+{
+ const CommonPageOptions opts(qbsProject, qbsProduct);
+
+ // Add 'Generic 8051 device' items,
+ // because we can't detect a target device
+ // form the present command lines.
+ appendProperty(QByteArrayLiteral("Device"),
+ QByteArrayLiteral("8051 (all Variants)"));
+ appendProperty(QByteArrayLiteral("Vendor"),
+ QByteArrayLiteral("Generic"));
+ appendProperty(QByteArrayLiteral("DeviceId"),
+ QByteArrayLiteral("2994"));
+
+ // Add 'Debug Information' item.
+ appendProperty(QByteArrayLiteral("DebugInformation"),
+ opts.debugInfo);
+ // Add 'Browse Information' item.
+ appendProperty(QByteArrayLiteral("BrowseInformation"),
+ opts.browseInfo);
+
+ // Add 'Name of Executable'.
+ appendProperty(QByteArrayLiteral("OutputName"),
+ opts.executableName);
+ // Add 'Output objects directory'.
+ appendProperty(QByteArrayLiteral("OutputDirectory"),
+ opts.objectDirectory);
+ // Add 'Output listing directory'.
+ appendProperty(QByteArrayLiteral("ListingPath"),
+ opts.listingDirectory);
+
+ // Add 'Create Executable/Library' item.
+ const int isExecutable = (opts.targetType
+ == KeiluvUtils::ApplicationOutputType);
+ const int isLibrary = (opts.targetType
+ == KeiluvUtils::LibraryOutputType);
+ appendProperty(QByteArrayLiteral("CreateExecutable"),
+ isExecutable);
+ appendProperty(QByteArrayLiteral("CreateLib"),
+ isLibrary);
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h
new file mode 100644
index 000000000..eccd9d42d
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H
+#define QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetCommonOptionsGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetCommonOptionsGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp
new file mode 100644
index 000000000..e33c0c211
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetcompilergroup_v5.h"
+#include "mcs51utils.h"
+
+#include "../../keiluvutils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+namespace {
+
+struct CompilerPageOptions final
+{
+ enum WarningLevel {
+ WarningLevelNone = 0,
+ WarningLevelOne,
+ WarningLevelTwo
+ };
+
+ enum OptimizationLevel {
+ ConstantFoldingOptimizationLevel = 0,
+ DeadCodeEliminationOptimizationLevel,
+ DataOverlayingOptimizationLevel,
+ PeepholeOptimizationLevel,
+ RegisterVariablesOptimizationLevel,
+ CommonSubexpressionEliminationOptimizationLevel,
+ LoopRotationOptimizationLevel,
+ ExtendedIndexAccessOptimizationLevel,
+ ReuseCommonEntryCodeOptimizationLevel,
+ CommonBlockSubroutinesOptimizationLevel,
+ RearrangeCodeOptimizationLevel,
+ ReuseCommonExitCodeOptimizationLevel
+ };
+
+ enum OptimizationEmphasis {
+ FavorSizeOptimizationEmphasis = 0,
+ FavorSpeedOptimizationEmphasis
+ };
+
+ enum FloatFuzzyBits {
+ NoFloatFuzzyBits = 0,
+ OneFloatFuzzyBit,
+ TwoFloatFuzzyBits,
+ ThreeFloatFuzzyBits,
+ FourFloatFuzzyBits,
+ FiveFloatFuzzyBits,
+ SixFloatFuzzyBits,
+ SevenFloatFuzzyBits
+ };
+
+ explicit CompilerPageOptions(const Project &qbsProject,
+ const ProductData &qbsProduct)
+ {
+ Q_UNUSED(qbsProject)
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps);
+
+ // Warnings.
+ const QString level = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("warningLevel"));
+ if (level == QLatin1String("none")) {
+ warningLevel = WarningLevelNone;
+ } else if (level == QLatin1String("all")) {
+ warningLevel = WarningLevelTwo;
+ } else {
+ // In this case take it directly from the compiler command line,
+ // e.g. parse the line in a form: 'WARNINGLEVEL (2)'
+ const auto warnValue = KeiluvUtils::flagValue(
+ flags, QStringLiteral("WARNINGLEVEL"));
+ bool ok = false;
+ const auto level = warnValue.toInt(&ok);
+ if (ok && gen::utils::inBounds(
+ level, int(WarningLevelNone),int(WarningLevelTwo))) {
+ warningLevel = static_cast<WarningLevel>(level);
+ }
+ }
+
+ // Optimizations.
+ const QString optimization = gen::utils::cppStringModuleProperty(
+ qbsProps, QStringLiteral("optimization"));
+ if (optimization == QLatin1String("fast")) {
+ optimizationEmphasis = FavorSpeedOptimizationEmphasis;
+ } else if (level == QLatin1String("small")) {
+ optimizationEmphasis = FavorSizeOptimizationEmphasis;
+ } else if (level == QLatin1String("small")) {
+ // Don't supported by C51 compiler.
+ } else {
+ // In this case take it directly from the compiler command line,
+ // e.g. parse the line in a form: 'OPTIMIZE (8, SPEED)'
+ const auto optValue = KeiluvUtils::flagValue(
+ flags, QStringLiteral("OPTIMIZE"));
+ const auto parts = KeiluvUtils::flagValueParts(optValue);
+ for (const auto &part : parts) {
+ bool ok = false;
+ const auto level = part.toInt(&ok);
+ if (ok && (level >= ConstantFoldingOptimizationLevel)
+ && (level <= ReuseCommonExitCodeOptimizationLevel)) {
+ optimizationLevel = static_cast<OptimizationLevel>(level);
+ } else if (part.compare(QLatin1String("SIZE"),
+ Qt::CaseInsensitive) == 0) {
+ optimizationEmphasis = FavorSizeOptimizationEmphasis;
+ } else if (part.compare(QLatin1String("SPEED"),
+ Qt::CaseInsensitive) == 0) {
+ optimizationEmphasis = FavorSpeedOptimizationEmphasis;
+ }
+ }
+ }
+
+ // Don't use absolute register accesses.
+ if (flags.contains(QLatin1String("NOAREGS"), Qt::CaseInsensitive))
+ dontuseAbsoluteRegsAccess = true;
+
+ // Enable ANSI integer promotion rules.
+ if (flags.contains(QLatin1String("NOINTPROMOTE"), Qt::CaseInsensitive))
+ enableIntegerPromotionRules = false;
+
+ // Keep variables in order.
+ if (flags.contains(QLatin1String("ORDER"), Qt::CaseInsensitive))
+ keepVariablesInOrder = true;
+
+ // Don't use interrupt vector.
+ if (flags.contains(QLatin1String("NOINTVECTOR"), Qt::CaseInsensitive))
+ useInterruptVector = false;
+
+ // Interrupt vector address.
+ interruptVectorAddress = KeiluvUtils::flagValue(
+ flags, QStringLiteral("INTVECTOR"));
+
+ // Float fuzzy bits count.
+ const auto bitsValue = KeiluvUtils::flagValue(
+ flags, QStringLiteral("FLOATFUZZY"));
+ bool ok = false;
+ const auto bits = bitsValue.toInt(&ok);
+ if (ok && gen::utils::inBounds(
+ bits, int(NoFloatFuzzyBits), int(SevenFloatFuzzyBits))) {
+ floatFuzzyBits = static_cast<FloatFuzzyBits>(bits);
+ }
+
+ // Define symbols.
+ defineSymbols = qbs::KeiluvUtils::defines(qbsProps);
+ // Include paths.
+ includePaths = qbs::KeiluvUtils::includes(qbsProps);
+
+ // Interpret other compiler flags as a misc controls (exclude only
+ // that flags which are was already handled).
+ for (const auto &flag : flags) {
+ if (flag.startsWith(QLatin1String("WARNINGLEVEL"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("OPTIMIZE"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("FLOATFUZZY"),
+ Qt::CaseInsensitive)
+ || flag.compare(QLatin1String("NOAREGS"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("AREGS"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("NOINTPROMOTE"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("INTPROMOTE"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("NOINTVECTOR"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("INTVECTOR"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("ORDER"),
+ Qt::CaseInsensitive) == 0
+ || flag.compare(QLatin1String("BROSWE"),
+ Qt::CaseInsensitive) == 0
+ ) {
+ continue;
+ }
+ miscControls.push_back(flag);
+ }
+ }
+
+ WarningLevel warningLevel = WarningLevelTwo;
+ OptimizationLevel optimizationLevel = ReuseCommonEntryCodeOptimizationLevel;
+ OptimizationEmphasis optimizationEmphasis = FavorSpeedOptimizationEmphasis;
+ FloatFuzzyBits floatFuzzyBits = ThreeFloatFuzzyBits;
+ int dontuseAbsoluteRegsAccess = false;
+ int enableIntegerPromotionRules = true;
+ int keepVariablesInOrder = false;
+ int useInterruptVector = true;
+ QString interruptVectorAddress;
+ QStringList defineSymbols;
+ QStringList includePaths;
+ QStringList miscControls;
+};
+
+} // namespace
+
+Mcs51TargetCompilerGroup::Mcs51TargetCompilerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("C51")
+{
+ const CompilerPageOptions opts(qbsProject, qbsProduct);
+
+ // Add 'Code Optimization' options.
+ appendProperty(QByteArrayLiteral("Optimize"),
+ opts.optimizationLevel);
+ appendProperty(QByteArrayLiteral("SizeSpeed"),
+ opts.optimizationEmphasis);
+ // Add 'Warnings' options.
+ appendProperty(QByteArrayLiteral("WarningLevel"),
+ opts.warningLevel);
+ // Add 'Don't use absolute register access' item.
+ appendProperty(QByteArrayLiteral("uAregs"),
+ opts.dontuseAbsoluteRegsAccess);
+ // Add 'Enable integer promotion rules' item.
+ appendProperty(QByteArrayLiteral("IntegerPromotion"),
+ opts.enableIntegerPromotionRules);
+ // Add 'Keep variables in order' item.
+ appendProperty(QByteArrayLiteral("VariablesInOrder"),
+ opts.keepVariablesInOrder);
+ // Add 'Use interrupt vector' item.
+ appendProperty(QByteArrayLiteral("UseInterruptVector"),
+ opts.useInterruptVector);
+ appendProperty(QByteArrayLiteral("InterruptVectorAddress"),
+ opts.interruptVectorAddress);
+ // Add 'Float fuzzy bits' item.
+ appendProperty(QByteArrayLiteral("Fuzzy"),
+ opts.floatFuzzyBits);
+
+ // Add other various controls.
+ // Note: A sub-items order makes sense!
+ const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("VariousControls"));
+ // Add 'Misc Controls' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("MiscControls"),
+ opts.miscControls, QLatin1Char(' '));
+ // Add 'Define' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("Define"),
+ opts.defineSymbols);
+ // Add an empty 'Undefine' item.
+ variousControlsGroup->appendProperty(
+ QByteArrayLiteral("Undefine"), {});
+ // Add 'Include Paths' item.
+ variousControlsGroup->appendMultiLineProperty(
+ QByteArrayLiteral("IncludePath"),
+ opts.includePaths, QLatin1Char(';'));
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h
new file mode 100644
index 000000000..0f1e52ce4
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H
+#define QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetCompilerGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetCompilerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp
new file mode 100644
index 000000000..2a05649dd
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetassemblergroup_v5.h"
+#include "mcs51targetcompilergroup_v5.h"
+#include "mcs51targetgroup_v5.h"
+#include "mcs51targetlinkergroup_v5.h"
+#include "mcs51targetmiscgroup_v5.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51TargetGroup::Mcs51TargetGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("Target51")
+{
+ appendChild<Mcs51TargetMiscGroup>(qbsProject, qbsProduct);
+ appendChild<Mcs51TargetCompilerGroup>(qbsProject, qbsProduct);
+ appendChild<Mcs51TargetAssemblerGroup>(qbsProject, qbsProduct);
+ appendChild<Mcs51TargetLinkerGroup>(qbsProject, qbsProduct);
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h
new file mode 100644
index 000000000..d256dfcc7
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETGROUP_V5_H
+#define QBS_KEILUVMCS51TARGETGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp
new file mode 100644
index 000000000..4d52b627a
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetlinkergroup_v5.h"
+#include "mcs51utils.h"
+
+#include "../../keiluvutils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+namespace {
+
+struct LinkerPageOptions final
+{
+ explicit LinkerPageOptions(const Project &qbsProject,
+ const ProductData &qbsProduct)
+ {
+ Q_UNUSED(qbsProject)
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto flags = qbs::KeiluvUtils::cppModuleLinkerFlags(qbsProps);
+
+ // Handle all 'BIT' memory flags.
+ parseMemory(flags, QStringLiteral("BIT"),
+ bitAddresses, bitSegments);
+ // Handle all 'CODE' memory flags.
+ parseMemory(flags, QStringLiteral("CODE"),
+ codeAddresses, codeSegments);
+ // Handle all 'DATA' memory flags.
+ parseMemory(flags, QStringLiteral("DATA"),
+ dataAddresses, dataSegments);
+ // Handle all 'IDATA' memory flags.
+ parseMemory(flags, QStringLiteral("IDATA"),
+ idataAddresses, idataSegments);
+ // Handle all 'PDATA' memory flags.
+ parseMemory(flags, QStringLiteral("PDATA"),
+ pdataAddresses, pdataSegments);
+ // Handle all 'XDATA' memory flags.
+ parseMemory(flags, QStringLiteral("XDATA"),
+ xdataAddresses, xdataSegments);
+
+ // Enumerate all flags in a form like:
+ // 'PRECEDE(foo, bar) PRECEDE(baz)'.
+ const auto precedeValues = KeiluvUtils::flagValues(
+ flags, QStringLiteral("PRECEDE"));
+ for (const auto &precedeValue : precedeValues) {
+ const auto parts = KeiluvUtils::flagValueParts(precedeValue);
+ precedeSegments.reserve(precedeSegments.size() + parts.count());
+ std::copy(parts.cbegin(), parts.cend(),
+ std::back_inserter(precedeSegments));
+ }
+
+ // Enumerate all flags in a form like:
+ // 'STACK(foo, bar) STACK(baz)'.
+ const auto stackValues = KeiluvUtils::flagValues(
+ flags, QStringLiteral("STACK"));
+ for (const auto &stackValue : stackValues) {
+ const auto parts = KeiluvUtils::flagValueParts(stackValue);
+ stackSegments.reserve(stackSegments.size() + parts.count());
+ std::copy(parts.cbegin(), parts.cend(),
+ std::back_inserter(stackSegments));
+ }
+
+ // Interpret other linker flags as a misc controls (exclude only
+ // that flags which are was already handled).
+ for (const auto &flag : flags) {
+ if (flag.startsWith(QLatin1String("BIT"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("CODE"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("DATA"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("IDATA"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("PDATA"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("XDATA"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("PRECEDE"),
+ Qt::CaseInsensitive)
+ || flag.startsWith(QLatin1String("STACK"),
+ Qt::CaseInsensitive)
+ ) {
+ continue;
+ }
+ miscControls.push_back(flag);
+ }
+ }
+
+ static void parseMemory(const QStringList &flags,
+ const QString &flagKey,
+ QStringList &destAddresses,
+ QStringList &destSegments)
+ {
+ // Handle all flags in a form like:
+ // 'FLAGKEY(0x00-0x20, 30, foo, bar(0x40)) FLAGKEY(baz)'.
+ const auto values = KeiluvUtils::flagValues(flags, flagKey);
+ for (const auto &value : values) {
+ const auto parts = KeiluvUtils::flagValueParts(value);
+ for (const auto &part : parts) {
+ if (part.contains(QLatin1Char('-'))) {
+ // Seems, it is an address range.
+ destAddresses.push_back(part);
+ } else {
+ // Check on address (specified in decimal
+ // or hexadecimal form).
+ bool ok = false;
+ part.toInt(&ok, 16);
+ if (!ok)
+ part.toInt(&ok, 10);
+ if (ok) {
+ // Seems, it is just a single address.
+ destAddresses.push_back(part);
+ } else {
+ // Seems it is a segment name.
+ destSegments.push_back(part);
+ }
+ }
+ }
+ }
+ }
+
+ QStringList bitAddresses;
+ QStringList bitSegments;
+ QStringList codeAddresses;
+ QStringList codeSegments;
+ QStringList dataAddresses;
+ QStringList dataSegments;
+ QStringList idataAddresses;
+ QStringList idataSegments;
+ QStringList pdataAddresses;
+ QStringList pdataSegments;
+ QStringList xdataAddresses;
+ QStringList xdataSegments;
+
+ QStringList precedeSegments;
+ QStringList stackSegments;
+
+ QStringList miscControls;
+};
+
+} // namespace
+
+Mcs51TargetLinkerGroup::Mcs51TargetLinkerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("Lx51")
+{
+ const LinkerPageOptions opts(qbsProject, qbsProduct);
+
+ // Add 'Misc Controls' item.
+ appendMultiLineProperty(QByteArrayLiteral("MiscControls"),
+ opts.miscControls, QLatin1Char(' '));
+
+ // Add 'Use Memory Layout from Target Dialog' item.
+ // Note: we always disable it, as we expect that
+ // the layout will be specified from the linker's
+ // command line.
+ appendProperty(QByteArrayLiteral("UseMemoryFromTarget"),
+ 0);
+
+ // Add 'Bit Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("BitBaseAddress"),
+ opts.bitAddresses);
+ // Add 'Code Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("CodeBaseAddress"),
+ opts.codeAddresses);
+ // Add 'Data Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("DataBaseAddress"),
+ opts.dataAddresses);
+ // Add 'IData Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("IDataBaseAddress"),
+ opts.idataAddresses);
+ // Add 'PData Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("PDataBaseAddress"),
+ opts.pdataAddresses);
+ // Add 'XData Range' item.
+ appendMultiLineProperty(QByteArrayLiteral("XDataBaseAddress"),
+ opts.xdataAddresses);
+
+ // Add 'Bit Segment' item.
+ appendMultiLineProperty(QByteArrayLiteral("BitSegmentName"),
+ opts.bitSegments);
+ // Add 'Code Segment' item.
+ appendMultiLineProperty(QByteArrayLiteral("CodeSegmentName"),
+ opts.codeSegments);
+ // Add 'Data Segment' item.
+ appendMultiLineProperty(QByteArrayLiteral("DataSegmentName"),
+ opts.dataSegments);
+ // Add 'IData Segment' item.
+ appendMultiLineProperty(QByteArrayLiteral("IDataSegmentName"),
+ opts.idataSegments);
+
+ // Note: PData has not segments!
+
+ // Add 'XData Segment' item.
+ appendMultiLineProperty(QByteArrayLiteral("XDataSegmentName"),
+ opts.xdataSegments);
+ // Add 'Precede' item.
+ appendMultiLineProperty(QByteArrayLiteral("Precede"),
+ opts.precedeSegments);
+ // Add 'Stack' item.
+ appendMultiLineProperty(QByteArrayLiteral("Stack"),
+ opts.stackSegments);
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h
new file mode 100644
index 000000000..d701c5e0e
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H
+#define QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetLinkerGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetLinkerGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp
new file mode 100644
index 000000000..5d95d443f
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51targetmiscgroup_v5.h"
+#include "mcs51utils.h"
+
+#include "../../keiluvutils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+namespace {
+
+struct MiscPageOptions final
+{
+ enum MemoryModel {
+ SmallMemoryModel = 0,
+ CompactMemoryModel,
+ LargeMemoryModel
+ };
+
+ enum CodeRomSize {
+ SmallCodeRomSize = 0,
+ CompactCodeRomSize,
+ LargeCodeRomSize
+ };
+
+ explicit MiscPageOptions(const Project &qbsProject,
+ const ProductData &qbsProduct)
+ {
+ Q_UNUSED(qbsProject)
+
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps);
+
+ // Memory model.
+ if (flags.contains(QLatin1String("COMPACT"), Qt::CaseInsensitive))
+ memoryModel = CompactMemoryModel;
+ else if (flags.contains(QLatin1String("LARGE"), Qt::CaseInsensitive))
+ memoryModel = LargeMemoryModel;
+
+ // Code ROM size.
+ const auto sizeValue = KeiluvUtils::flagValue(
+ flags, QStringLiteral("ROM"));
+ if (sizeValue == QLatin1String("SMALL"))
+ coderomSize = SmallCodeRomSize;
+ else if (sizeValue == QLatin1String("COMPACT"))
+ coderomSize = CompactCodeRomSize;
+ }
+
+ MemoryModel memoryModel = SmallMemoryModel;
+ CodeRomSize coderomSize = LargeCodeRomSize;
+};
+
+} // namespace
+
+Mcs51TargetMiscGroup::Mcs51TargetMiscGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("Target51Misc")
+{
+ const MiscPageOptions opts(qbsProject, qbsProduct);
+
+ // Add 'Memory Model' options item.
+ appendProperty(QByteArrayLiteral("MemoryModel"),
+ opts.memoryModel);
+ // Add 'ROM Size' options item.
+ appendProperty(QByteArrayLiteral("RomSize"),
+ opts.coderomSize);
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h
new file mode 100644
index 000000000..f1680d927
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51TARGETMISCGROUP_V5_H
+#define QBS_KEILUVMCS51TARGETMISCGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51TargetMiscGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51TargetMiscGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51TARGETMISCGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp
new file mode 100644
index 000000000..8e8307f72
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51utilitiesgroup_v5.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+Mcs51UtilitiesGroup::Mcs51UtilitiesGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct)
+ : gen::xml::PropertyGroup("Utilities")
+{
+ Q_UNUSED(qbsProject)
+ Q_UNUSED(qbsProduct)
+}
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h
new file mode 100644
index 000000000..f95ec67c4
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51UTILITIESGROUP_V5_H
+#define QBS_KEILUVMCS51UTILITIESGROUP_V5_H
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+namespace v5 {
+
+class Mcs51UtilitiesGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit Mcs51UtilitiesGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct);
+};
+
+} // namespace v5
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51UTILITIESGROUP_V5_H
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp
new file mode 100644
index 000000000..698f0df78
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "mcs51utils.h"
+
+namespace qbs {
+namespace keiluv {
+namespace mcs51 {
+
+namespace KeiluvUtils {
+
+static QString extractValue(const QString &flag)
+{
+ const auto openBracketIndex = flag.indexOf(QLatin1Char('('));
+ const auto closeBracketIndex = flag.indexOf(QLatin1Char(')'));
+ const auto n = closeBracketIndex - openBracketIndex - 1;
+ return flag.mid(openBracketIndex + 1, n);
+}
+
+QStringList flagValues(const QStringList &flags, const QString &flagKey)
+{
+ QStringList values;
+ for (const auto &flag : flags) {
+ if (!flag.startsWith(flagKey, Qt::CaseInsensitive))
+ continue;
+ const auto value = extractValue(flag);
+ values.push_back(value);
+ }
+ return values;
+}
+
+QString flagValue(const QStringList &flags, const QString &flagKey)
+{
+ const auto flagEnd = flags.cend();
+ const auto flagIt = std::find_if(flags.cbegin(), flagEnd,
+ [flagKey](const auto &flag) {
+ return flag.startsWith(flagKey, Qt::CaseInsensitive);
+ });
+ if (flagIt == flagEnd)
+ return {}; // Flag key not found.
+ return extractValue(*flagIt);
+}
+
+QStringList flagValueParts(const QString &flagValue, const QLatin1Char &sep)
+{
+ auto parts = flagValue.split(sep);
+ std::transform(parts.begin(), parts.end(), parts.begin(),
+ [](const auto &part) { return part.trimmed(); });
+ return parts;
+}
+
+} // namespace KeiluvUtils
+
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h
new file mode 100644
index 000000000..f6ed7e4eb
--- /dev/null
+++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVMCS51UTILS_H
+#define QBS_KEILUVMCS51UTILS_H
+
+#include <QtCore/qstringlist.h>
+
+namespace qbs {
+
+namespace keiluv {
+namespace mcs51 {
+
+namespace KeiluvUtils {
+
+QStringList flagValues(const QStringList &flags, const QString &flagKey);
+
+QString flagValue(const QStringList &flags, const QString &flagKey);
+
+QStringList flagValueParts(const QString &flagValue,
+ const QLatin1Char &sep = QLatin1Char(','));
+
+} // namespace KeiluvUtils
+
+namespace v5 {
+
+namespace KeiluvConstants {
+
+constexpr int kUVisionVersion = 5;
+
+} // namespace KeiluvConstants
+
+} // namespace v5
+
+} // namespace mcs51
+} // namespace keiluv
+} // namespace qbs
+
+#endif // QBS_KEILUVMCS51UTILS_H
+
diff --git a/src/plugins/generator/keiluv/keiluv.pro b/src/plugins/generator/keiluv/keiluv.pro
new file mode 100644
index 000000000..d260adea1
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluv.pro
@@ -0,0 +1,63 @@
+include(../../plugins.pri)
+include(../../../shared/json/json.pri)
+
+TARGET = keiluvgenerator
+
+QT = core
+
+# Plugin file.
+
+SOURCES += \
+ $$PWD/keiluvgeneratorplugin.cpp \
+
+# Common files.
+
+HEADERS += \
+ $$PWD/keiluvfilesgroupspropertygroup.h \
+ $$PWD/keiluvgenerator.h \
+ $$PWD/keiluvproject.h \
+ $$PWD/keiluvprojectwriter.h \
+ $$PWD/keiluvutils.h \
+ $$PWD/keiluvversioninfo.h \
+ $$PWD/keiluvworkspace.h \
+ $$PWD/keiluvworkspacewriter.h
+
+SOURCES += \
+ $$PWD/keiluvfilesgroupspropertygroup.cpp \
+ $$PWD/keiluvgenerator.cpp \
+ $$PWD/keiluvproject.cpp \
+ $$PWD/keiluvprojectwriter.cpp \
+ $$PWD/keiluvutils.cpp \
+ $$PWD/keiluvversioninfo.cpp \
+ $$PWD/keiluvworkspace.cpp \
+ $$PWD/keiluvworkspacewriter.cpp
+
+# For MCS51 architecture.
+
+HEADERS += \
+ $$PWD/archs/mcs51/mcs51buildtargetgroup_v5.h \
+ $$PWD/archs/mcs51/mcs51commonpropertygroup_v5.h \
+ $$PWD/archs/mcs51/mcs51debugoptiongroup_v5.h \
+ $$PWD/archs/mcs51/mcs51dlloptiongroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetassemblergroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetcompilergroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetgroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetlinkergroup_v5.h \
+ $$PWD/archs/mcs51/mcs51targetmiscgroup_v5.h \
+ $$PWD/archs/mcs51/mcs51utilitiesgroup_v5.h \
+ $$PWD/archs/mcs51/mcs51utils.h
+
+SOURCES += \
+ $$PWD/archs/mcs51/mcs51buildtargetgroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51commonpropertygroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51debugoptiongroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51dlloptiongroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetassemblergroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetcompilergroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetgroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetlinkergroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51targetmiscgroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51utilitiesgroup_v5.cpp \
+ $$PWD/archs/mcs51/mcs51utils.cpp
diff --git a/src/plugins/generator/keiluv/keiluv.qbs b/src/plugins/generator/keiluv/keiluv.qbs
new file mode 100644
index 000000000..62e03593c
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluv.qbs
@@ -0,0 +1,62 @@
+import qbs
+import "../../qbsplugin.qbs" as QbsPlugin
+
+QbsPlugin {
+ Depends { name: "qbsjson" }
+
+ name: "keiluvgenerator"
+
+ files: ["keiluvgeneratorplugin.cpp"]
+
+ Group {
+ name: "KEIL UV generator common"
+ files: [
+ "keiluvfilesgroupspropertygroup.cpp",
+ "keiluvfilesgroupspropertygroup.h",
+ "keiluvgenerator.cpp",
+ "keiluvgenerator.h",
+ "keiluvproject.cpp",
+ "keiluvproject.h",
+ "keiluvprojectwriter.cpp",
+ "keiluvprojectwriter.h",
+ "keiluvutils.cpp",
+ "keiluvutils.h",
+ "keiluvversioninfo.cpp",
+ "keiluvversioninfo.h",
+ "keiluvworkspace.cpp",
+ "keiluvworkspace.h",
+ "keiluvworkspacewriter.cpp",
+ "keiluvworkspacewriter.h",
+ ]
+ }
+ Group {
+ name: "KEIL UV generator for MCS51"
+ prefix: "archs/mcs51/"
+ files: [
+ "mcs51buildtargetgroup_v5.cpp",
+ "mcs51buildtargetgroup_v5.h",
+ "mcs51commonpropertygroup_v5.cpp",
+ "mcs51commonpropertygroup_v5.h",
+ "mcs51debugoptiongroup_v5.cpp",
+ "mcs51debugoptiongroup_v5.h",
+ "mcs51dlloptiongroup_v5.cpp",
+ "mcs51dlloptiongroup_v5.h",
+ "mcs51targetassemblergroup_v5.cpp",
+ "mcs51targetassemblergroup_v5.h",
+ "mcs51targetcommonoptionsgroup_v5.cpp",
+ "mcs51targetcommonoptionsgroup_v5.h",
+ "mcs51targetcompilergroup_v5.cpp",
+ "mcs51targetcompilergroup_v5.h",
+ "mcs51targetgroup_v5.cpp",
+ "mcs51targetgroup_v5.h",
+ "mcs51targetlinkergroup_v5.cpp",
+ "mcs51targetlinkergroup_v5.h",
+ "mcs51targetmiscgroup_v5.cpp",
+ "mcs51targetmiscgroup_v5.h",
+ "mcs51utilitiesgroup_v5.cpp",
+ "mcs51utilitiesgroup_v5.h",
+ "mcs51utils.cpp",
+ "mcs51utils.h",
+ ]
+ }
+}
diff --git a/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp
new file mode 100644
index 000000000..b9a234d6a
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "keiluvfilesgroupspropertygroup.h"
+#include "keiluvutils.h"
+
+#include <generators/generatordata.h>
+
+#include <tools/stringconstants.h>
+
+namespace qbs {
+
+class KeiluvFilePropertyGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit KeiluvFilePropertyGroup(
+ const QString &fullFilePath,
+ const QString &baseDirectory)
+ : gen::xml::PropertyGroup("File")
+ {
+ const QFileInfo fileInfo(fullFilePath);
+ const auto fileName = fileInfo.fileName();
+ const auto fileType = encodeFileType(fileInfo.suffix());
+ const auto filePath = QDir::toNativeSeparators(
+ gen::utils::relativeFilePath(
+ baseDirectory,
+ fileInfo.absoluteFilePath()));
+
+ appendChild<gen::xml::Property>(QByteArrayLiteral("FileName"),
+ fileName);
+ appendChild<gen::xml::Property>(QByteArrayLiteral("FileType"),
+ fileType);
+ appendChild<gen::xml::Property>(QByteArrayLiteral("FilePath"),
+ filePath);
+ }
+
+private:
+ enum FileType {
+ UnknownFileType = 0,
+ CSourceFileType = 1,
+ AssemblerFileType = 2,
+ LibraryFileType = 4,
+ TextFileType = 5,
+ CppSourceFileType = 8,
+ };
+
+ static FileType encodeFileType(const QString &fileSuffix)
+ {
+ if (fileSuffix.compare(QLatin1String("c"),
+ Qt::CaseInsensitive) == 0) {
+ return CSourceFileType;
+ } else if (fileSuffix.compare(QLatin1String("cpp"),
+ Qt::CaseInsensitive) == 0) {
+ return CppSourceFileType;
+ } else if (fileSuffix.compare(QLatin1String("s"),
+ Qt::CaseInsensitive) == 0
+ || fileSuffix.compare(QLatin1String("a51"),
+ Qt::CaseInsensitive) == 0) {
+ return AssemblerFileType;
+ } else if (fileSuffix.compare(QLatin1String("lib"),
+ Qt::CaseInsensitive) == 0) {
+ return LibraryFileType;
+ } else {
+ // All header files, text files and include files
+ // interpretes as a text file types.
+ return TextFileType;
+ }
+ }
+};
+
+class KeiluvFilesPropertyGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit KeiluvFilesPropertyGroup(
+ const QList<ArtifactData> &sourceArtifacts,
+ const QString &baseDirectory)
+ : gen::xml::PropertyGroup("Files")
+ {
+ for (const auto &artifact : sourceArtifacts)
+ appendChild<KeiluvFilePropertyGroup>(artifact.filePath(),
+ baseDirectory);
+ }
+
+ explicit KeiluvFilesPropertyGroup(
+ const QStringList &filePaths,
+ const QString &baseDirectory)
+ : gen::xml::PropertyGroup("Files")
+ {
+ for (const auto &filePath : filePaths)
+ appendChild<KeiluvFilePropertyGroup>(filePath,
+ baseDirectory);
+ }
+};
+
+class KeiluvFileGroupPropertyGroup final : public gen::xml::PropertyGroup
+{
+public:
+ explicit KeiluvFileGroupPropertyGroup(
+ const QString &groupName,
+ const QList<ArtifactData> &sourceArtifacts,
+ const QString &baseDirectory)
+ : gen::xml::PropertyGroup("Group")
+ {
+ appendChild<gen::xml::Property>(QByteArrayLiteral("GroupName"),
+ groupName);
+
+ appendChild<KeiluvFilesPropertyGroup>(sourceArtifacts,
+ baseDirectory);
+ }
+
+ explicit KeiluvFileGroupPropertyGroup(
+ const QString &groupName,
+ const QStringList &filePaths,
+ const QString &baseDirectory)
+ : gen::xml::PropertyGroup("Group")
+ {
+ appendChild<gen::xml::Property>(QByteArrayLiteral("GroupName"),
+ groupName);
+
+ appendChild<KeiluvFilesPropertyGroup>(filePaths,
+ baseDirectory);
+ }
+};
+
+KeiluvFilesGroupsPropertyGroup::KeiluvFilesGroupsPropertyGroup(
+ const Project &qbsProject,
+ const ProductData &qbsProduct,
+ const std::vector<ProductData> &qbsProductDeps)
+ : gen::xml::PropertyGroup(QByteArrayLiteral("Groups"))
+{
+ const auto baseDirectory = gen::utils::buildRootPath(qbsProject);
+
+ // Build source items.
+ const auto groups = qbsProduct.groups();
+ for (const auto &group : groups) {
+ // Ignore disabled groups (e.g. when its condition property is false).
+ if (!group.isEnabled())
+ continue;
+ auto sourceArtifacts = group.sourceArtifacts();
+ // Remove the linker script artifacts.
+ sourceArtifacts.erase(std::remove_if(sourceArtifacts.begin(),
+ sourceArtifacts.end(),
+ [](const auto &artifact){
+ const auto tags = artifact.fileTags();
+ return tags.contains(QLatin1String("linkerscript"));
+ }), sourceArtifacts.end());
+
+ if (sourceArtifacts.isEmpty())
+ continue;
+ appendChild<KeiluvFileGroupPropertyGroup>(
+ group.name(), sourceArtifacts, baseDirectory);
+ }
+
+ // Build local static library items.
+ const auto &qbsProps = qbsProduct.moduleProperties();
+ const auto staticLibs = KeiluvUtils::staticLibraries(qbsProps);
+ if (!staticLibs.isEmpty()) {
+ appendChild<KeiluvFileGroupPropertyGroup>(
+ QStringLiteral("Static Libs"), staticLibs, baseDirectory);
+ }
+
+ // Build dependency library items.
+ const auto deps = KeiluvUtils::dependencies(qbsProductDeps);
+ if (!deps.isEmpty()) {
+ appendChild<KeiluvFileGroupPropertyGroup>(
+ QStringLiteral("Dependencies"), deps, baseDirectory);
+ }
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h
new file mode 100644
index 000000000..bde86b89c
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVFILESGROUPSPROPERTYGROUP_H
+#define QBS_KEILUVFILESGROUPSPROPERTYGROUP_H
+
+#include <generators/xmlpropertygroup.h>
+
+#include <generators/generatordata.h>
+
+namespace qbs {
+
+class KeiluvFilesGroupsPropertyGroup final
+ : public gen::xml::PropertyGroup
+{
+public:
+ explicit KeiluvFilesGroupsPropertyGroup(
+ const qbs::Project &qbsProject,
+ const qbs::ProductData &qbsProduct,
+ const std::vector<qbs::ProductData> &qbsProductDeps);
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVFILESGROUPSPROPERTYGROUP_H
diff --git a/src/plugins/generator/keiluv/keiluvgenerator.cpp b/src/plugins/generator/keiluv/keiluvgenerator.cpp
new file mode 100644
index 000000000..657a98ad4
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvgenerator.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "keiluvgenerator.h"
+#include "keiluvproject.h"
+#include "keiluvprojectwriter.h"
+#include "keiluvworkspace.h"
+#include "keiluvworkspacewriter.h"
+
+#include <generators/generatableprojectiterator.h>
+
+#include <logging/logger.h>
+#include <logging/translator.h>
+
+#include <tools/filesaver.h>
+
+namespace qbs {
+
+static QString targetFilePath(const QString &baseName,
+ const QString &baseBuildDirectory)
+{
+ return QDir(baseBuildDirectory).absoluteFilePath(
+ baseName + QStringLiteral(".uvproj"));
+}
+
+static QString targetFilePath(const GeneratableProductData &product,
+ const QString &baseBuildDirectory)
+{
+ return targetFilePath(product.name(), baseBuildDirectory);
+}
+
+static void writeProjectFiles(const std::map<QString,
+ std::shared_ptr<KeiluvProject>> &projects,
+ const Internal::Logger &logger)
+{
+ for (const auto &item : projects) {
+ const QString projectFilePath = item.first;
+ Internal::FileSaver file(projectFilePath.toStdString());
+ if (!file.open())
+ throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing")
+ .arg(projectFilePath));
+
+ std::shared_ptr<KeiluvProject> project = item.second;
+ KeiluvProjectWriter writer(file.device());
+ if (!(writer.write(project.get()) && file.commit()))
+ throw ErrorInfo(Internal::Tr::tr("Failed to generate %1")
+ .arg(projectFilePath));
+
+ logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg(
+ QFileInfo(projectFilePath).fileName());
+ }
+}
+
+static void writeWorkspace(const std::shared_ptr<KeiluvWorkspace> &wokspace,
+ const QString &workspaceFilePath,
+ const Internal::Logger &logger)
+{
+ Internal::FileSaver file(workspaceFilePath.toStdString());
+ if (!file.open())
+ throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing")
+ .arg(workspaceFilePath));
+
+ KeiluvWorkspaceWriter writer(file.device());
+ if (!(writer.write(wokspace.get()) && file.commit()))
+ throw ErrorInfo(Internal::Tr::tr("Failed to generate %1")
+ .arg(workspaceFilePath));
+
+ logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg(
+ QFileInfo(workspaceFilePath).fileName());
+}
+
+KeiluvGenerator::KeiluvGenerator(const KeiluvVersionInfo &versionInfo)
+ : m_versionInfo(versionInfo)
+{
+}
+
+QString KeiluvGenerator::generatorName() const
+{
+ return QStringLiteral("keiluv%1").arg(m_versionInfo.marketingVersion());
+}
+
+void KeiluvGenerator::reset()
+{
+ m_workspace.reset();
+ m_workspaceFilePath.clear();
+ m_projects.clear();
+}
+
+void KeiluvGenerator::generate()
+{
+ GeneratableProjectIterator it(project());
+ it.accept(this);
+
+ writeProjectFiles(m_projects, logger());
+ writeWorkspace(m_workspace, m_workspaceFilePath, logger());
+
+ reset();
+}
+
+void KeiluvGenerator::visitProject(const GeneratableProject &project)
+{
+ const QDir buildDir = project.baseBuildDirectory();
+
+ m_workspaceFilePath = buildDir.absoluteFilePath(
+ project.name() + QStringLiteral(".uvmpw"));
+ m_workspace = std::make_shared<KeiluvWorkspace>(m_workspaceFilePath);
+}
+
+void KeiluvGenerator::visitProjectData(
+ const GeneratableProject &project,
+ const GeneratableProjectData &projectData)
+{
+ Q_UNUSED(project)
+ Q_UNUSED(projectData)
+}
+
+void KeiluvGenerator::visitProduct(
+ const GeneratableProject &project,
+ const GeneratableProjectData &projectData,
+ const GeneratableProductData &productData)
+{
+ Q_UNUSED(projectData);
+ const QString projectFilePath = targetFilePath(
+ productData, project.baseBuildDirectory().absolutePath());
+ const auto targetProject = std::make_shared<KeiluvProject>(
+ project, productData, m_versionInfo);
+
+ m_projects.insert({projectFilePath, targetProject});
+ m_workspace->addProject(projectFilePath);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvgenerator.h b/src/plugins/generator/keiluv/keiluvgenerator.h
new file mode 100644
index 000000000..769519562
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvgenerator.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVGENERATOR_H
+#define QBS_KEILUVGENERATOR_H
+
+#include "keiluvversioninfo.h"
+
+#include <generators/generator.h>
+#include <generators/igeneratableprojectvisitor.h>
+
+namespace qbs {
+
+class KeiluvProject;
+class KeiluvWorkspace;
+
+class KeiluvGenerator final : public ProjectGenerator,
+ private IGeneratableProjectVisitor
+{
+public:
+ explicit KeiluvGenerator(const KeiluvVersionInfo &versionInfo);
+
+ QString generatorName() const final;
+ void generate() final;
+
+private:
+ void reset();
+
+ void visitProject(const GeneratableProject &project) final;
+ void visitProjectData(const GeneratableProject &project,
+ const GeneratableProjectData &projectData) final;
+ void visitProduct(const GeneratableProject &project,
+ const GeneratableProjectData &projectData,
+ const GeneratableProductData &productData) final;
+
+ const KeiluvVersionInfo m_versionInfo;
+ std::shared_ptr<KeiluvWorkspace> m_workspace;
+ QString m_workspaceFilePath;
+ std::map<QString, std::shared_ptr<KeiluvProject>> m_projects;
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVGENERATOR_H
diff --git a/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp b/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp
new file mode 100644
index 000000000..33e552936
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "keiluvgenerator.h"
+#include "keiluvversioninfo.h"
+
+#include <tools/projectgeneratormanager.h>
+#include <tools/qbspluginmanager.h>
+
+static void QbsKeiluvGeneratorPluginLoad()
+{
+ for (const auto &info : qbs::KeiluvVersionInfo::knownVersions()) {
+ qbs::ProjectGeneratorManager::registerGenerator(
+ std::make_shared<qbs::KeiluvGenerator>(info));
+ }
+}
+
+static void QbsKeiluvGeneratorPluginUnload()
+{
+}
+
+#ifndef GENERATOR_EXPORT
+#if defined(WIN32) || defined(_WIN32)
+#define GENERATOR_EXPORT __declspec(dllexport)
+#else
+#define GENERATOR_EXPORT __attribute__((visibility("default")))
+#endif
+#endif
+
+QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsKeiluvGeneratorPlugin,
+ QbsKeiluvGeneratorPluginLoad, QbsKeiluvGeneratorPluginUnload)
diff --git a/src/plugins/generator/keiluv/keiluvproject.cpp b/src/plugins/generator/keiluv/keiluvproject.cpp
new file mode 100644
index 000000000..bd5e80658
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvproject.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 "keiluvproject.h"
+#include "keiluvutils.h"
+#include "keiluvversioninfo.h"
+
+#include "archs/mcs51/mcs51buildtargetgroup_v5.h"
+#include "archs/mcs51/mcs51utils.h"
+
+#include <logging/translator.h>
+
+namespace qbs {
+
+static QString keilProjectSchema(const KeiluvVersionInfo &info)
+{
+ const auto v = info.marketingVersion();
+ switch (v) {
+ case keiluv::mcs51::v5::KeiluvConstants::kUVisionVersion:
+ return QStringLiteral("1.1");
+ default:
+ return {};
+ }
+}
+
+KeiluvProject::KeiluvProject(
+ const qbs::GeneratableProject &genProject,
+ const qbs::GeneratableProductData &genProduct,
+ const KeiluvVersionInfo &versionInfo)
+{
+ Q_ASSERT(genProject.projects.size() == genProject.commandLines.size());
+ Q_ASSERT(genProject.projects.size() == genProduct.data.size());
+
+ // Create available configuration group factories.
+ m_factories.push_back(std::make_unique<
+ keiluv::mcs51::v5::Mcs51BuildTargetGroupFactory>());
+
+ // Construct schema version item (depends on a project version).
+ const auto schema = keilProjectSchema(versionInfo);
+ appendChild<gen::xml::Property>(QByteArrayLiteral("SchemaVersion"),
+ schema);
+
+ // Construct targets group.
+ const auto targetsGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("Targets"));
+
+ // Construct all build target items.
+ const int configsCount = std::max(genProject.projects.size(),
+ genProduct.data.size());
+ for (auto configIndex = 0; configIndex < configsCount; ++configIndex) {
+ const qbs::Project qbsProject = genProject.projects
+ .values().at(configIndex);
+ const qbs::ProductData qbsProduct = genProduct.data
+ .values().at(configIndex);
+ const QString confName = gen::utils::buildConfigurationName(qbsProject);
+ const std::vector<ProductData> qbsProductDeps = gen::utils::dependenciesOf
+ (qbsProduct, genProject, confName);
+
+ const auto arch = gen::utils::architecture(qbsProject);
+ if (arch == gen::utils::Architecture::Unknown)
+ throw ErrorInfo(Internal::Tr::tr("Target architecture is not set,"
+ " please use the 'profile' option"));
+
+ // Construct the build target item, which are depend from
+ // the architecture and the version.
+ const auto factoryEnd = m_factories.cend();
+ const auto factoryIt = std::find_if(m_factories.cbegin(), factoryEnd,
+ [arch, versionInfo](const auto &factory) {
+ return factory->canCreate(arch, versionInfo.version());
+ });
+ if (factoryIt == factoryEnd) {
+ throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'"
+ " for KEIL UV version %2")
+ .arg(gen::utils::architectureName(arch))
+ .arg(versionInfo.marketingVersion()));
+ }
+
+ auto targetGroup = (*factoryIt)->create(
+ qbsProject, qbsProduct, qbsProductDeps);
+ targetsGroup->appendChild(std::move(targetGroup));
+ }
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvproject.h b/src/plugins/generator/keiluv/keiluvproject.h
new file mode 100644
index 000000000..98b2815ed
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvproject.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVPROJECT_H
+#define QBS_KEILUVPROJECT_H
+
+#include <generators/generatordata.h>
+
+#include <generators/xmlproject.h>
+#include <generators/xmlpropertygroup.h>
+
+#include <memory>
+
+namespace qbs {
+
+class KeiluvVersionInfo;
+
+class KeiluvProject final : public gen::xml::Project
+{
+public:
+ explicit KeiluvProject(
+ const qbs::GeneratableProject &genProject,
+ const qbs::GeneratableProductData &genProduct,
+ const KeiluvVersionInfo &versionInfo);
+private:
+ std::vector<std::unique_ptr<gen::xml::PropertyGroupFactory>> m_factories;
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVPROJECT_H
diff --git a/src/plugins/generator/keiluv/keiluvprojectwriter.cpp b/src/plugins/generator/keiluv/keiluvprojectwriter.cpp
new file mode 100644
index 000000000..f2ae8befb
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvprojectwriter.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "keiluvprojectwriter.h"
+
+namespace qbs {
+
+KeiluvProjectWriter::KeiluvProjectWriter(std::ostream *device)
+ : gen::xml::ProjectWriter(device)
+{
+}
+
+void KeiluvProjectWriter::visitStart(const gen::xml::Project *project)
+{
+ Q_UNUSED(project)
+ writer()->writeStartElement(QStringLiteral("Project"));
+ writer()->writeAttribute(
+ QStringLiteral("xmlns:xsi"),
+ QStringLiteral("http://www.w3.org/2001/XMLSchema-instance"));
+ writer()->writeAttribute(
+ QStringLiteral("xsi:noNamespaceSchemaLocation"),
+ QStringLiteral("project_proj.xsd"));
+}
+
+void KeiluvProjectWriter::visitEnd(const gen::xml::Project *project)
+{
+ Q_UNUSED(project)
+ writer()->writeEndElement();
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvprojectwriter.h b/src/plugins/generator/keiluv/keiluvprojectwriter.h
new file mode 100644
index 000000000..ad6fd1124
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvprojectwriter.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVPROJECTWRITER_H
+#define QBS_KEILUVPROJECTWRITER_H
+
+#include <generators/xmlprojectwriter.h>
+
+namespace qbs {
+
+class KeiluvProjectWriter final : public gen::xml::ProjectWriter
+{
+ Q_DISABLE_COPY(KeiluvProjectWriter)
+public:
+ explicit KeiluvProjectWriter(std::ostream *device);
+
+private:
+ void visitStart(const gen::xml::Project *project) final;
+ void visitEnd(const gen::xml::Project *project) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVPROJECTWRITER_H
diff --git a/src/plugins/generator/keiluv/keiluvutils.cpp b/src/plugins/generator/keiluv/keiluvutils.cpp
new file mode 100644
index 000000000..8932f0f16
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvutils.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "keiluvutils.h"
+
+#include <generators/generatorutils.h>
+
+namespace qbs {
+namespace KeiluvUtils {
+
+OutputBinaryType outputBinaryType(const ProductData &qbsProduct)
+{
+ const auto qbsProductType = qbsProduct.type();
+ if (qbsProductType.contains(QLatin1String("application")))
+ return ApplicationOutputType;
+ if (qbsProductType.contains(QLatin1String("staticlibrary")))
+ return LibraryOutputType;
+ return ApplicationOutputType;
+}
+
+QString toolkitRootPath(const ProductData &qbsProduct)
+{
+ QDir dir(qbsProduct.moduleProperties()
+ .getModuleProperty(Internal::StringConstants::cppModule(),
+ QStringLiteral("toolchainInstallPath"))
+ .toString());
+ dir.cdUp();
+ const auto path = dir.absolutePath();
+ return QDir::toNativeSeparators(path);
+}
+
+QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"),
+ QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"),
+ QStringLiteral("commonCompilerFlags")});
+}
+
+QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("assemblerFlags")});
+}
+
+QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("driverLinkerFlags")});
+}
+
+QStringList includes(const PropertyMap &qbsProps)
+{
+ auto paths = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("includePaths"),
+ QStringLiteral("systemIncludePaths")});
+ // Transform include path separators to native.
+ std::transform(paths.begin(), paths.end(), paths.begin(),
+ [](const auto &path) {
+ return QDir::toNativeSeparators(path);
+ });
+ return paths;
+}
+
+QStringList defines(const PropertyMap &qbsProps)
+{
+ return gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("defines")});
+}
+
+QStringList staticLibraries(const PropertyMap &qbsProps)
+{
+ auto libs = gen::utils::cppStringModuleProperties(
+ qbsProps, {QStringLiteral("staticLibraries")});
+ // Transform library path separators to native.
+ std::transform(libs.begin(), libs.end(), libs.begin(),
+ [](const auto &path) {
+ return QDir::toNativeSeparators(path);
+ });
+ return libs;
+}
+
+QStringList dependencies(const std::vector<ProductData> &qbsProductDeps)
+{
+ QStringList deps;
+ for (const ProductData &qbsProductDep : qbsProductDeps) {
+ const auto path = qbsProductDep.buildDirectory()
+ + QLatin1String("/obj/")
+ + gen::utils::targetBinary(qbsProductDep);
+ deps.push_back(QDir::toNativeSeparators(path));
+ }
+ return deps;
+}
+
+} // namespace KeiluvUtils
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvutils.h b/src/plugins/generator/keiluv/keiluvutils.h
new file mode 100644
index 000000000..92209dc53
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvutils.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVUTILS_H
+#define QBS_KEILUVUTILS_H
+
+#include <qbs.h>
+
+#include <tools/stringconstants.h>
+
+namespace qbs {
+namespace KeiluvUtils {
+
+enum OutputBinaryType {
+ ApplicationOutputType,
+ LibraryOutputType
+};
+
+OutputBinaryType outputBinaryType(const ProductData &qbsProduct);
+
+QString toolkitRootPath(const ProductData &qbsProduct);
+
+QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps);
+
+QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps);
+
+QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps);
+
+QStringList includes(const PropertyMap &qbsProps);
+QStringList defines(const PropertyMap &qbsProps);
+QStringList staticLibraries(const PropertyMap &qbsProps);
+QStringList dependencies(const std::vector<ProductData> &qbsProductDeps);
+
+} // namespace KeiluvUtils
+} // namespace qbs
+
+#endif // QBS_KEILUVUTILS_H
diff --git a/src/plugins/generator/keiluv/keiluvversioninfo.cpp b/src/plugins/generator/keiluv/keiluvversioninfo.cpp
new file mode 100644
index 000000000..544a07aff
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvversioninfo.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "keiluvversioninfo.h"
+
+#include "archs/mcs51/mcs51utils.h"
+
+#include <QtCore/qdebug.h>
+
+namespace qbs {
+
+KeiluvVersionInfo::KeiluvVersionInfo(
+ const Version &version,
+ const std::set<gen::utils::Architecture> &archs)
+ : gen::VersionInfo(version, archs)
+{
+}
+
+std::set<KeiluvVersionInfo> KeiluvVersionInfo::knownVersions()
+{
+ static const std::set<KeiluvVersionInfo> known = {
+ {Version(keiluv::mcs51::v5::KeiluvConstants::kUVisionVersion),
+ {gen::utils::Architecture::Mcs51}},
+ };
+ return known;
+}
+
+int KeiluvVersionInfo::marketingVersion() const
+{
+ const auto mv = gen::VersionInfo::marketingVersion();
+ for (const KeiluvVersionInfo &known : knownVersions()) {
+ if (known.version().majorVersion() == mv)
+ return mv;
+ }
+ qWarning() << QStringLiteral("Unrecognized KEIL UV version: ")
+ << version().toString();
+ return 0;
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvversioninfo.h b/src/plugins/generator/keiluv/keiluvversioninfo.h
new file mode 100644
index 000000000..a64513492
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvversioninfo.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVVERSIONINFO_H
+#define QBS_KEILUVVERSIONINFO_H
+
+#include <generators/generatorutils.h>
+#include <generators/generatorversioninfo.h>
+
+namespace qbs {
+
+class KeiluvVersionInfo final : public gen::VersionInfo
+{
+public:
+ KeiluvVersionInfo(const Version &version,
+ const std::set<gen::utils::Architecture> &archs);
+
+ int marketingVersion() const final;
+
+ static std::set<KeiluvVersionInfo> knownVersions();
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVVERSIONINFO_H
diff --git a/src/plugins/generator/keiluv/keiluvworkspace.cpp b/src/plugins/generator/keiluv/keiluvworkspace.cpp
new file mode 100644
index 000000000..b4df92001
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvworkspace.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "keiluvworkspace.h"
+
+#include <generators/xmlpropertygroup.h>
+
+namespace qbs {
+
+KeiluvWorkspace::KeiluvWorkspace(const QString &workspacePath)
+ : gen::xml::Workspace(workspacePath)
+{
+ // Construct schema version item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("SchemaVersion"),
+ QStringLiteral("1.0"));
+
+ // Construct workspace name item.
+ appendChild<gen::xml::Property>(QByteArrayLiteral("WorkspaceName"),
+ QStringLiteral("WorkSpace"));
+}
+
+void KeiluvWorkspace::addProject(const QString &projectFilePath)
+{
+ const QString relativeProjectPath = QDir::toNativeSeparators(
+ m_baseDirectory.relativeFilePath(projectFilePath));
+
+ const auto projectGroup = appendChild<gen::xml::PropertyGroup>(
+ QByteArrayLiteral("project"));
+ projectGroup->appendProperty("PathAndName", relativeProjectPath);
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvworkspace.h b/src/plugins/generator/keiluv/keiluvworkspace.h
new file mode 100644
index 000000000..2b274c99f
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvworkspace.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVWORKSPACE_H
+#define QBS_KEILUVWORKSPACE_H
+
+#include <generators/xmlworkspace.h>
+
+namespace qbs {
+
+class KeiluvWorkspace final : public gen::xml::Workspace
+{
+public:
+ explicit KeiluvWorkspace(const QString &workspacePath);
+ void addProject(const QString &projectPath) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVWORKSPACE_H
diff --git a/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp b/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp
new file mode 100644
index 000000000..9070a2542
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "keiluvworkspacewriter.h"
+
+namespace qbs {
+
+KeiluvWorkspaceWriter::KeiluvWorkspaceWriter(std::ostream *device)
+ : gen::xml::WorkspaceWriter(device)
+{
+}
+
+void KeiluvWorkspaceWriter::visitStart(const gen::xml::Workspace *workspace)
+{
+ Q_UNUSED(workspace)
+ writer()->writeStartElement(QStringLiteral("ProjectWorkspace"));
+ writer()->writeAttribute(
+ QStringLiteral("xmlns:xsi"),
+ QStringLiteral("http://www.w3.org/2001/XMLSchema-instance"));
+ writer()->writeAttribute(
+ QStringLiteral("xsi:noNamespaceSchemaLocation"),
+ QStringLiteral("project_mpw.xsd"));
+}
+
+void KeiluvWorkspaceWriter::visitEnd(const gen::xml::Workspace *workspace)
+{
+ Q_UNUSED(workspace)
+ writer()->writeEndElement();
+}
+
+} // namespace qbs
diff --git a/src/plugins/generator/keiluv/keiluvworkspacewriter.h b/src/plugins/generator/keiluv/keiluvworkspacewriter.h
new file mode 100644
index 000000000..56bcd1ebc
--- /dev/null
+++ b/src/plugins/generator/keiluv/keiluvworkspacewriter.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_KEILUVWORKSPACEWRITER_H
+#define QBS_KEILUVWORKSPACEWRITER_H
+
+#include <generators/xmlworkspacewriter.h>
+
+namespace qbs {
+
+class KeiluvWorkspaceWriter final : public gen::xml::WorkspaceWriter
+{
+ Q_DISABLE_COPY(KeiluvWorkspaceWriter)
+public:
+ explicit KeiluvWorkspaceWriter(std::ostream *device);
+
+private:
+ void visitStart(const gen::xml::Workspace *workspace) final;
+ void visitEnd(const gen::xml::Workspace *workspace) final;
+};
+
+} // namespace qbs
+
+#endif // QBS_KEILUVWORKSPACEWRITER_H
diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs
index dcc1ded87..ee101f60e 100644
--- a/src/plugins/plugins.qbs
+++ b/src/plugins/plugins.qbs
@@ -6,6 +6,8 @@ Project {
"generator/clangcompilationdb/clangcompilationdb.qbs",
"generator/makefilegenerator/makefilegenerator.qbs",
"generator/visualstudio/visualstudio.qbs",
+ "generator/iarew/iarew.qbs",
+ "generator/keiluv/keiluv.qbs",
"scanner/cpp/cpp.qbs",
"scanner/qt/qt.qbs"
]
diff --git a/tests/auto/api/testdata/timeout-js/timeout.qbs b/tests/auto/api/testdata/timeout-js/timeout.qbs
new file mode 100644
index 000000000..26aa4ce87
--- /dev/null
+++ b/tests/auto/api/testdata/timeout-js/timeout.qbs
@@ -0,0 +1,20 @@
+Product {
+ type: "product-under-test"
+ Rule {
+ multiplex: true
+ Artifact {
+ filePath: "output.txt"
+ fileTags: "product-under-test"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "Running infinite loop";
+ cmd.sourceCode = function() {
+ while (true)
+ ;
+ }
+ cmd.timeout = 3;
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/api/testdata/timeout-process/main.cpp b/tests/auto/api/testdata/timeout-process/main.cpp
new file mode 100644
index 000000000..f9b9336ba
--- /dev/null
+++ b/tests/auto/api/testdata/timeout-process/main.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <chrono>
+#include <thread>
+
+int main()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(700));
+ return 0;
+}
+
diff --git a/tests/auto/api/testdata/timeout-process/timeout.qbs b/tests/auto/api/testdata/timeout-process/timeout.qbs
new file mode 100644
index 000000000..9f1491ff4
--- /dev/null
+++ b/tests/auto/api/testdata/timeout-process/timeout.qbs
@@ -0,0 +1,24 @@
+Project {
+ CppApplication {
+ type: "application"
+ consoleApplication: true // suppress bundle generation
+ files: "main.cpp"
+ name: "infinite-loop"
+ }
+
+ Product {
+ type: "product-under-test"
+ name: "caller"
+ Depends { name: "infinite-loop" }
+ Rule {
+ inputsFromDependencies: "application"
+ outputFileTags: "product-under-test"
+ prepare: {
+ var cmd = new Command(inputs["application"][0].filePath);
+ cmd.description = "Calling application that runs forever";
+ cmd.timeout = 3;
+ return cmd;
+ }
+ }
+ }
+}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index aac0f3e7e..b47d3b5c8 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -2829,6 +2830,69 @@ void TestApi::targetArtifactStatus()
QCOMPARE(product.targetArtifacts().size(), enableTagging ? 2 : 1);
}
+void TestApi::timeout()
+{
+ QFETCH(QString, projectDirName);
+ QFETCH(qint64, expectedMaxRunTime);
+ const auto setupParams = defaultSetupParameters(projectDirName + "/timeout.qbs");
+ std::unique_ptr<qbs::SetupProjectJob> setupJob{
+ qbs::Project().setupProject(setupParams, m_logSink, nullptr)};
+ waitForFinished(setupJob.get());
+ QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString()));
+ auto project = setupJob->project();
+ const auto products = project.projectData().products();
+ QList<qbs::ProductData> helperProducts;
+ qbs::ProductData productUnderTest;
+ for (const auto &product : products) {
+ if (!product.type().contains(QLatin1String("product-under-test")))
+ helperProducts.append(product);
+ else
+ productUnderTest = product;
+ }
+ const std::unique_ptr<qbs::BuildJob> buildHelpersJob{
+ project.buildSomeProducts(helperProducts, qbs::BuildOptions())};
+ QVERIFY(waitForFinished(buildHelpersJob.get(), testTimeoutInMsecs()));
+ if (buildHelpersJob->error().hasError()) {
+ qDebug().noquote() << buildHelpersJob->error().toString();
+ QFAIL("Could not build helper products");
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+ const std::unique_ptr<qbs::BuildJob> buildJob(project.buildOneProduct(productUnderTest,
+ qbs::BuildOptions()));
+ const auto testAbortTimeout = 20 * 1000ll;
+ /* We add an additional buffer to the expectedMaxRunTime because Qbs can take some
+ * time (>1 second) to finish after the command has been cancelled.
+ */
+ expectedMaxRunTime += 4 * 1000ll;
+ Q_ASSERT_X(testAbortTimeout > expectedMaxRunTime,
+ Q_FUNC_INFO,
+ "testAbortTimeout must be larger than the expectedMaxRunTime. Else the "
+ "test might be cancelled to early although the code is working correctly.");
+ QTimer::singleShot(testAbortTimeout, buildJob.get(), &qbs::AbstractJob::cancel);
+ QVERIFY(waitForFinished(buildJob.get(), testTimeoutInMsecs()));
+ const auto actualRunTime = timer.elapsed();
+ QVERIFY(buildJob->error().hasError());
+ const auto errorString = buildJob->error().toString();
+ QVERIFY(errorString.contains("cancel"));
+ QVERIFY(errorString.contains("timeout"));
+ if (actualRunTime > expectedMaxRunTime)
+ qDebug() << actualRunTime << "vs." << expectedMaxRunTime;
+ QVERIFY(actualRunTime < expectedMaxRunTime);
+}
+
+void TestApi::timeout_data()
+{
+ QTest::addColumn<QString>("projectDirName");
+ QTest::addColumn<qint64>("expectedMaxRunTime");
+ QTest::newRow("JS Command") << QString("timeout-js") << 3 * 1000ll;
+ /* The timeout is 3 seconds. Qbs will try to terminate the process for 3 seconds and then kill
+ * it.
+ */
+ QTest::newRow("Process Command") << QString("timeout-process") << (3 + 3) * 1000ll;
+}
+
void TestApi::toolInModule()
{
QVariantMap overrides({std::make_pair("qbs.installRoot", m_workingDataDir
diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h
index c04e9feb0..ce1678133 100644
--- a/tests/auto/api/tst_api.h
+++ b/tests/auto/api/tst_api.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -142,6 +143,8 @@ private slots:
void subProjects();
void targetArtifactStatus_data();
void targetArtifactStatus();
+ void timeout();
+ void timeout_data();
void toolInModule();
void trackAddQObjectHeader();
void trackRemoveQObjectHeader();
diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs
index 1ab369c88..221105a64 100644
--- a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs
+++ b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs
@@ -63,7 +63,7 @@ Project {
outputFileTags: "tool_in"
outputArtifacts: {
var artifacts = [];
- for (var i = 0; i < 7; ++i)
+ for (var i = 0; i < 5; ++i)
artifacts.push({filePath: "file" + i + ".in", fileTags: "tool_in"});
return artifacts;
}
diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp b/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp
index 0a94c6393..ec9acba80 100644
--- a/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp
+++ b/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
return 4;
}
}
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
fclose(lockFile);
std::FILE * const output = std::fopen(argv[1], "w");
if (!output) {
diff --git a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs
new file mode 100644
index 000000000..2cc20c3fd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs
@@ -0,0 +1,9 @@
+Project {
+ CppApplication {
+ name: "testApp"
+ type: ["application", "autotest"]
+ Depends { name: "autotest" }
+ files: "test-main.cpp"
+ }
+ AutotestRunner {}
+}
diff --git a/tests/auto/blackbox/testdata/autotest-timeout/test-main.cpp b/tests/auto/blackbox/testdata/autotest-timeout/test-main.cpp
new file mode 100644
index 000000000..4bb1ca27c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/autotest-timeout/test-main.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <chrono>
+#include <thread>
+
+int main()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ return 0;
+}
+
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index f87889155..edc2b51c8 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -5624,6 +5625,34 @@ void TestBlackbox::autotestWithDependencies()
&& m_qbsStdout.contains("i am the helper"), m_qbsStdout.constData());
}
+void TestBlackbox::autotestTimeout()
+{
+ QFETCH(QStringList, resolveParams);
+ QFETCH(bool, expectFailure);
+ QDir::setCurrent(testDataDir + "/autotest-timeout");
+ QbsRunParameters resolveParameters("resolve", resolveParams);
+ QCOMPARE(runQbs(resolveParameters), 0);
+ QbsRunParameters buildParameters(QStringList({"-p", "autotest-runner"}));
+ buildParameters.expectFailure = expectFailure;
+ if (expectFailure) {
+ QVERIFY(runQbs(buildParameters) != 0);
+ QVERIFY(m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout"));
+ }
+ else
+ QVERIFY(runQbs(buildParameters) == 0);
+}
+
+void TestBlackbox::autotestTimeout_data()
+{
+ QTest::addColumn<QStringList>("resolveParams");
+ QTest::addColumn<bool>("expectFailure");
+ QTest::newRow("no timeout") << QStringList() << false;
+ QTest::newRow("timeout on test") << QStringList({"products.testApp.autotest.timeout:2"})
+ << true;
+ QTest::newRow("timeout on runner") << QStringList({"products.autotest-runner.timeout:2"})
+ << true;
+}
+
void TestBlackbox::autotests_data()
{
QTest::addColumn<QString>("evilPropertySpec");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 0a14c418c..4c1268912 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de>
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
@@ -48,6 +49,8 @@ private slots:
void artifactScanning();
void assembly();
void autotestWithDependencies();
+ void autotestTimeout();
+ void autotestTimeout_data();
void autotests_data();
void autotests();
void auxiliaryInputsFromDependencies();
diff --git a/tests/auto/blackbox/tst_blackboxjoblimits.cpp b/tests/auto/blackbox/tst_blackboxjoblimits.cpp
index 0c366759d..89b5f638e 100644
--- a/tests/auto/blackbox/tst_blackboxjoblimits.cpp
+++ b/tests/auto/blackbox/tst_blackboxjoblimits.cpp
@@ -165,7 +165,7 @@ void TestBlackboxJobLimits::jobLimits()
else
QVERIFY2(m_qbsStderr.contains("exclusive"), m_qbsStderr.constData());
if (exitCode == 0)
- QCOMPARE(m_qbsStdout.count("Running tool"), 7);
+ QCOMPARE(m_qbsStdout.count("Running tool"), 5);
}
QTEST_MAIN(TestBlackboxJobLimits)