1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include "profileevaluator.h" |
5 | |
6 | #include "qmakeglobals.h" |
7 | #include "ioutils.h" |
8 | #include "qmakevfs.h" |
9 | |
10 | #include <QDir> |
11 | |
12 | using namespace QMakeInternal; |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | void ProFileEvaluator::initialize() |
17 | { |
18 | QMakeEvaluator::initStatics(); |
19 | } |
20 | |
21 | ProFileEvaluator::ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeVfs *vfs, |
22 | QMakeHandler *handler) |
23 | : d(new QMakeEvaluator(option, parser, vfs, handler)) |
24 | { |
25 | } |
26 | |
27 | ProFileEvaluator::~ProFileEvaluator() |
28 | { |
29 | delete d; |
30 | } |
31 | |
32 | bool ProFileEvaluator::contains(const QString &variableName) const |
33 | { |
34 | return d->m_valuemapStack.top().contains(key: ProKey(variableName)); |
35 | } |
36 | |
37 | QString ProFileEvaluator::value(const QString &variable) const |
38 | { |
39 | const QStringList &vals = values(variableName: variable); |
40 | if (!vals.isEmpty()) |
41 | return vals.first(); |
42 | |
43 | return QString(); |
44 | } |
45 | |
46 | QStringList ProFileEvaluator::values(const QString &variableName) const |
47 | { |
48 | const ProStringList &values = d->values(variableName: ProKey(variableName)); |
49 | QStringList ret; |
50 | ret.reserve(asize: values.size()); |
51 | for (const ProString &str : values) |
52 | ret << d->m_option->expandEnvVars(str: str.toQString()); |
53 | return ret; |
54 | } |
55 | |
56 | QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const |
57 | { |
58 | // It makes no sense to put any kind of magic into expanding these |
59 | const ProStringList &values = d->m_valuemapStack.front().value(key: ProKey(variableName)); |
60 | QStringList ret; |
61 | ret.reserve(asize: values.size()); |
62 | for (const ProString &str : values) |
63 | if (str.sourceFile() == pro->id()) |
64 | ret << d->m_option->expandEnvVars(str: str.toQString()); |
65 | return ret; |
66 | } |
67 | |
68 | QString ProFileEvaluator::sysrootify(const QString &path, const QString &baseDir) const |
69 | { |
70 | ProFileGlobals *option = static_cast<ProFileGlobals *>(d->m_option); |
71 | #ifdef Q_OS_WIN |
72 | Qt::CaseSensitivity cs = Qt::CaseInsensitive; |
73 | #else |
74 | Qt::CaseSensitivity cs = Qt::CaseSensitive; |
75 | #endif |
76 | const bool isHostSystemPath = |
77 | option->sysroot.isEmpty() || path.startsWith(s: option->sysroot, cs) |
78 | || path.startsWith(s: baseDir, cs) || path.startsWith(s: d->m_outputDir, cs); |
79 | |
80 | return isHostSystemPath ? path : option->sysroot + path; |
81 | } |
82 | |
83 | QStringList ProFileEvaluator::absolutePathValues( |
84 | const QString &variable, const QString &baseDirectory) const |
85 | { |
86 | QStringList result; |
87 | for (const QString &el : values(variableName: variable)) { |
88 | QString absEl = IoUtils::isAbsolutePath(fileName: el) |
89 | ? sysrootify(path: el, baseDir: baseDirectory) : IoUtils::resolvePath(baseDir: baseDirectory, fileName: el); |
90 | if (IoUtils::fileType(fileName: absEl) == IoUtils::FileIsDir) |
91 | result << QDir::cleanPath(path: absEl); |
92 | } |
93 | return result; |
94 | } |
95 | |
96 | QStringList ProFileEvaluator::absoluteFileValues( |
97 | const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, |
98 | const ProFile *pro) const |
99 | { |
100 | QStringList result; |
101 | const auto vals = pro ? values(variableName: variable, pro) : values(variableName: variable); |
102 | for (const QString &el : vals) { |
103 | QString absEl; |
104 | if (IoUtils::isAbsolutePath(fileName: el)) { |
105 | const QString elWithSysroot = QDir::cleanPath(path: sysrootify(path: el, baseDir: baseDirectory)); |
106 | if (d->m_vfs->exists(fn: elWithSysroot, flags: QMakeVfs::VfsCumulative)) { |
107 | result << elWithSysroot; |
108 | goto next; |
109 | } |
110 | absEl = elWithSysroot; |
111 | } else { |
112 | for (const QString &dir : searchDirs) { |
113 | QString fn = QDir::cleanPath(path: dir + QLatin1Char('/') + el); |
114 | if (d->m_vfs->exists(fn, flags: QMakeVfs::VfsCumulative)) { |
115 | result << fn; |
116 | goto next; |
117 | } |
118 | } |
119 | if (baseDirectory.isEmpty()) |
120 | goto next; |
121 | absEl = QDir::cleanPath(path: baseDirectory + QLatin1Char('/') + el); |
122 | } |
123 | { |
124 | int nameOff = absEl.lastIndexOf(c: QLatin1Char('/')); |
125 | QString absDir = d->m_tmp1.setRawData(unicode: absEl.constData(), size: nameOff); |
126 | // NOTE: This does not support virtual files. That shouldn't be a problem, |
127 | // because no sane project would add generated files by wildcard. |
128 | if (IoUtils::fileType(fileName: absDir) == IoUtils::FileIsDir) { |
129 | QString wildcard = d->m_tmp2.setRawData(unicode: absEl.constData() + nameOff + 1, |
130 | size: absEl.size() - nameOff - 1); |
131 | if (wildcard.contains(c: QLatin1Char('*')) || wildcard.contains(c: QLatin1Char('?'))) { |
132 | QDir theDir(absDir); |
133 | for (const QString &fn : theDir.entryList(nameFilters: QStringList(wildcard))) |
134 | if (fn != QLatin1String("." ) && fn != QLatin1String(".." )) |
135 | result << absDir + QLatin1Char('/') + fn; |
136 | } // else if (acceptMissing) |
137 | } |
138 | } |
139 | next: ; |
140 | } |
141 | return result; |
142 | } |
143 | |
144 | ProFileEvaluator::TemplateType ProFileEvaluator::templateType() const |
145 | { |
146 | const ProStringList &templ = d->values(variableName: ProKey("TEMPLATE" )); |
147 | if (templ.size() >= 1) { |
148 | const QString &t = templ.at(i: 0).toQString(); |
149 | if (!t.compare(other: QLatin1String("app" ), cs: Qt::CaseInsensitive)) |
150 | return TT_Application; |
151 | if (!t.compare(other: QLatin1String("lib" ), cs: Qt::CaseInsensitive)) |
152 | return TT_Library; |
153 | if (!t.compare(other: QLatin1String("script" ), cs: Qt::CaseInsensitive)) |
154 | return TT_Script; |
155 | if (!t.compare(other: QLatin1String("aux" ), cs: Qt::CaseInsensitive)) |
156 | return TT_Aux; |
157 | if (!t.compare(other: QLatin1String("subdirs" ), cs: Qt::CaseInsensitive)) |
158 | return TT_Subdirs; |
159 | } |
160 | return TT_Unknown; |
161 | } |
162 | |
163 | bool ProFileEvaluator::loadNamedSpec(const QString &specDir, bool hostSpec) |
164 | { |
165 | d->m_qmakespec = specDir; |
166 | d->m_hostBuild = hostSpec; |
167 | |
168 | d->updateMkspecPaths(); |
169 | return d->loadSpecInternal(); |
170 | } |
171 | |
172 | bool ProFileEvaluator::accept(ProFile *pro, QMakeEvaluator::LoadFlags flags) |
173 | { |
174 | return d->visitProFile(pro, type: QMakeHandler::EvalProjectFile, flags) == QMakeEvaluator::ReturnTrue; |
175 | } |
176 | |
177 | QString ProFileEvaluator::propertyValue(const QString &name) const |
178 | { |
179 | return d->m_option->propertyValue(name: ProKey(name)).toQString(); |
180 | } |
181 | |
182 | QString ProFileEvaluator::resolvedMkSpec() const |
183 | { |
184 | return d->m_qmakespec; |
185 | } |
186 | |
187 | #ifdef PROEVALUATOR_CUMULATIVE |
188 | void ProFileEvaluator::setCumulative(bool on) |
189 | { |
190 | d->m_cumulative = on; |
191 | } |
192 | #endif |
193 | |
194 | void ProFileEvaluator::(const QHash<QString, QStringList> &) |
195 | { |
196 | ProValueMap map; |
197 | for (auto it = extraVars.cbegin(), end = extraVars.cend() ; it != end; ++it) |
198 | map.insert(key: ProKey(it.key()), value: ProStringList(it.value())); |
199 | d->setExtraVars(map); |
200 | } |
201 | |
202 | void ProFileEvaluator::(const QStringList &) |
203 | { |
204 | d->setExtraConfigs(ProStringList(extraConfigs)); |
205 | } |
206 | |
207 | void ProFileEvaluator::setOutputDir(const QString &dir) |
208 | { |
209 | d->m_outputDir = dir; |
210 | } |
211 | |
212 | QT_END_NAMESPACE |
213 | |