1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
4 ** Contact: http://www.qt.io/licensing
5 **
6 ** This file is part of Qbs.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms and
13 ** conditions see http://www.qt.io/terms-conditions. For further information
14 ** use the contact form at http://www.qt.io/contact-us.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 or version 3 as published by the Free
19 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
20 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
21 ** following information to ensure the GNU Lesser General Public License
22 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
23 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, The Qt Company gives you certain additional
26 ** rights. These rights are described in The Qt Company LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ****************************************************************************/
30
31 #include "generatorutils.h"
32
33 namespace qbs {
34 namespace gen {
35 namespace utils {
36
architectureName(Architecture arch)37 QString architectureName(Architecture arch)
38 {
39 switch (arch) {
40 case Architecture::Arm:
41 return QStringLiteral("arm");
42 case Architecture::Avr:
43 return QStringLiteral("avr");
44 case Architecture::Mcs51:
45 return QStringLiteral("mcs51");
46 default:
47 return QStringLiteral("unknown");
48 }
49 }
50
architecture(const Project & qbsProject)51 Architecture architecture(const Project &qbsProject)
52 {
53 const auto qbsArch = qbsProject.projectConfiguration()
54 .value(Internal::StringConstants::qbsModule()).toMap()
55 .value(QStringLiteral("architecture")).toString();
56
57 if (qbsArch == QLatin1String("arm"))
58 return Architecture::Arm;
59 if (qbsArch == QLatin1String("avr"))
60 return Architecture::Avr;
61 if (qbsArch == QLatin1String("mcs51"))
62 return Architecture::Mcs51;
63 if (qbsArch == QLatin1String("stm8"))
64 return Architecture::Stm8;
65 if (qbsArch == QLatin1String("msp430"))
66 return Architecture::Msp430;
67 return Architecture::Unknown;
68 }
69
buildConfigurationName(const Project & qbsProject)70 QString buildConfigurationName(const Project &qbsProject)
71 {
72 return qbsProject.projectConfiguration()
73 .value(Internal::StringConstants::qbsModule()).toMap()
74 .value(QStringLiteral("configurationName")).toString();
75 }
76
debugInformation(const ProductData & qbsProduct)77 int debugInformation(const ProductData &qbsProduct)
78 {
79 return qbsProduct.moduleProperties().getModuleProperty(
80 Internal::StringConstants::qbsModule(),
81 QStringLiteral("debugInformation"))
82 .toInt();
83 }
84
buildRootPath(const Project & qbsProject)85 QString buildRootPath(const Project &qbsProject)
86 {
87 QDir dir(qbsProject.projectData().buildDirectory());
88 dir.cdUp();
89 return dir.absolutePath();
90 }
91
relativeFilePath(const QString & baseDirectory,const QString & fullFilePath)92 QString relativeFilePath(const QString &baseDirectory,
93 const QString &fullFilePath)
94 {
95 return QDir(baseDirectory).relativeFilePath(fullFilePath);
96 }
97
binaryOutputDirectory(const QString & baseDirectory,const ProductData & qbsProduct)98 QString binaryOutputDirectory(const QString &baseDirectory,
99 const ProductData &qbsProduct)
100 {
101 return QDir(baseDirectory).relativeFilePath(
102 qbsProduct.buildDirectory())
103 + QLatin1String("/bin");
104 }
105
objectsOutputDirectory(const QString & baseDirectory,const ProductData & qbsProduct)106 QString objectsOutputDirectory(const QString &baseDirectory,
107 const ProductData &qbsProduct)
108 {
109 return QDir(baseDirectory).relativeFilePath(
110 qbsProduct.buildDirectory())
111 + QLatin1String("/obj");
112 }
113
listingOutputDirectory(const QString & baseDirectory,const ProductData & qbsProduct)114 QString listingOutputDirectory(const QString &baseDirectory,
115 const ProductData &qbsProduct)
116 {
117 return QDir(baseDirectory).relativeFilePath(
118 qbsProduct.buildDirectory())
119 + QLatin1String("/lst");
120 }
121
dependenciesOf(const ProductData & qbsProduct,const GeneratableProject & genProject,const QString & configurationName)122 std::vector<ProductData> dependenciesOf(const ProductData &qbsProduct,
123 const GeneratableProject &genProject,
124 const QString &configurationName)
125 {
126 std::vector<ProductData> result;
127 const auto &depsNames = qbsProduct.dependencies();
128 for (const auto &product : qAsConst(genProject.products)) {
129 const auto pt = product.type();
130 if (!pt.contains(QLatin1String("staticlibrary")))
131 continue;
132 const auto pn = product.name();
133 if (!depsNames.contains(pn))
134 continue;
135 result.push_back(product.data.value(configurationName));
136 }
137 return result;
138 }
139
targetBinary(const ProductData & qbsProduct)140 QString targetBinary(const ProductData &qbsProduct)
141 {
142 const auto &type = qbsProduct.type();
143 if (type.contains(QLatin1String("application"))) {
144 return QFileInfo(qbsProduct.targetExecutable()).fileName();
145 } else if (type.contains(QLatin1String("staticlibrary"))) {
146 for (const auto &artifact : qbsProduct.targetArtifacts()) {
147 if (artifact.fileTags().contains(QLatin1String("staticlibrary")))
148 return QFileInfo(artifact.filePath()).fileName();
149 }
150 }
151
152 return {};
153 }
154
targetBinaryPath(const QString & baseDirectory,const ProductData & qbsProduct)155 QString targetBinaryPath(const QString &baseDirectory,
156 const ProductData &qbsProduct)
157 {
158 return binaryOutputDirectory(baseDirectory, qbsProduct)
159 + QLatin1Char('/') + targetBinary(qbsProduct);
160 }
161
cppStringModuleProperty(const PropertyMap & qbsProps,const QString & propertyName)162 QString cppStringModuleProperty(const PropertyMap &qbsProps,
163 const QString &propertyName)
164 {
165 return qbsProps.getModuleProperty(
166 Internal::StringConstants::cppModule(),
167 propertyName).toString().trimmed();
168 }
169
cppBooleanModuleProperty(const PropertyMap & qbsProps,const QString & propertyName)170 bool cppBooleanModuleProperty(const PropertyMap &qbsProps,
171 const QString &propertyName)
172 {
173 return qbsProps.getModuleProperty(
174 Internal::StringConstants::cppModule(),
175 propertyName).toBool();
176 }
177
cppIntegerModuleProperty(const PropertyMap & qbsProps,const QString & propertyName)178 int cppIntegerModuleProperty(const PropertyMap &qbsProps,
179 const QString &propertyName)
180 {
181 return qbsProps.getModuleProperty(
182 Internal::StringConstants::cppModule(),
183 propertyName).toInt();
184 }
185
cppStringModuleProperties(const PropertyMap & qbsProps,const QStringList & propertyNames)186 QStringList cppStringModuleProperties(const PropertyMap &qbsProps,
187 const QStringList &propertyNames)
188 {
189 QStringList properties;
190 for (const auto &propertyName : propertyNames) {
191 const auto entries = qbsProps.getModuleProperty(
192 Internal::StringConstants::cppModule(),
193 propertyName).toStringList();
194 for (const auto &entry : entries)
195 properties.push_back(entry.trimmed());
196 }
197 return properties;
198 }
199
cppVariantModuleProperties(const PropertyMap & qbsProps,const QStringList & propertyNames)200 QVariantList cppVariantModuleProperties(const PropertyMap &qbsProps,
201 const QStringList &propertyNames)
202 {
203 QVariantList properties;
204 for (const auto &propertyName : propertyNames) {
205 properties << qbsProps.getModuleProperty(
206 Internal::StringConstants::cppModule(),
207 propertyName).toList();
208 }
209 return properties;
210 }
211
parseFlagValue(const QString & flagKey,QStringList::const_iterator & flagIt,const QStringList::const_iterator & flagEnd)212 static QString parseFlagValue(const QString &flagKey,
213 QStringList::const_iterator &flagIt,
214 const QStringList::const_iterator &flagEnd)
215 {
216 if (flagIt->contains(QLatin1Char('='))) {
217 // In this case an option is in form of 'flagKey=<flagValue>'.
218 const auto parts = flagIt->split(QLatin1Char('='));
219 if (parts.count() == 2)
220 return parts.at(1).trimmed();
221 } else if (flagKey < *flagIt) {
222 // In this case an option is in form of 'flagKey<flagValue>'.
223 return flagIt->mid(flagKey.count()).trimmed();
224 } else {
225 // In this case an option is in form of 'flagKey <flagValue>'.
226 ++flagIt;
227 if (flagIt < flagEnd && !flagIt->startsWith(QLatin1Char('-')))
228 return (*flagIt).trimmed();
229 }
230 return {};
231 }
232
firstFlagValue(const QStringList & flags,const QString & flagKey)233 QString firstFlagValue(const QStringList &flags, const QString &flagKey)
234 {
235 const auto flagBegin = flags.cbegin();
236 const auto flagEnd = flags.cend();
237 auto flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) {
238 return flag == flagKey || flag.startsWith(flagKey);
239 });
240 if (flagIt == flagEnd)
241 return {};
242 return parseFlagValue(flagKey, flagIt, flagEnd);
243 }
244
allFlagValues(const QStringList & flags,const QString & flagKey)245 QStringList allFlagValues(const QStringList &flags, const QString &flagKey)
246 {
247 QStringList values;
248 const auto flagEnd = flags.cend();
249 for (auto flagIt = flags.cbegin(); flagIt < flagEnd; ++flagIt) {
250 if (*flagIt == flagKey || flagIt->startsWith(flagKey)) {
251 const QString value = parseFlagValue(flagKey, flagIt, flagEnd);
252 if (!value.isEmpty())
253 values.push_back(value);
254 }
255 }
256 return values;
257 }
258
259 } // namespace utils
260 } // namespace gen
261 } // namespace qbs
262