qmakeevaluator.h 11.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3
4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
** 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
Eike Ziller's avatar
Eike Ziller committed
12
13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** 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.
24
**
Eike Ziller's avatar
Eike Ziller committed
25
26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
27
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
30
31
32
33

#ifndef QMAKEEVALUATOR_H
#define QMAKEEVALUATOR_H

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
34
35
36
37
#if defined(PROEVALUATOR_FULL) && defined(PROEVALUATOR_THREAD_SAFE)
#  error PROEVALUATOR_FULL is incompatible with PROEVALUATOR_THREAD_SAFE due to cache() implementation
#endif

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
38
#include "qmakeparser.h"
39
40
#include "ioutils.h"

41
#include <qiodevice.h>
42
43
#include <qlist.h>
#include <qlinkedlist.h>
44
#include <qmap.h>
45
46
47
48
#include <qset.h>
#include <qstack.h>
#include <qstring.h>
#include <qstringlist.h>
49
#include <qshareddata.h>
50
#ifndef QT_BOOTSTRAPPED
51
# include <qprocess.h>
52
#endif
53
54
55
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qmutex.h>
#endif
56
57
58

QT_BEGIN_NAMESPACE

59
60
class QMakeGlobals;

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
61
class QMAKE_EXPORT QMakeHandler : public QMakeParserHandler
62
63
{
public:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
64
65
66
    enum {
        SourceEvaluator = 0x10,

67
68
69
        EvalWarnLanguage = SourceEvaluator |  WarningMessage | WarnLanguage,
        EvalWarnDeprecated = SourceEvaluator | WarningMessage | WarnDeprecated,

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
70
71
72
73
        EvalError = ErrorMessage | SourceEvaluator
    };

    // error(), warning() and message() from .pro file
74
75
76
77
78
79
80
    virtual void fileMessage(const QString &msg) = 0;

    enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
    virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0;
    virtual void doneWithEval(ProFile *parent) = 0;
};

81
82
83
84
85
86
87
88
89
90
91
92
93
94
typedef QPair<QString, QString> QMakeFeatureKey; // key, parent
typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash;

class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData
{
public:
    QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {}
    const QStringList paths;
    mutable QMakeFeatureHash cache;
#ifdef PROEVALUATOR_THREAD_SAFE
    mutable QMutex mutex;
#endif
};

95
96
97
98
99
100
101
102
103
104
// We use a QLinkedList based stack instead of a QVector based one (QStack), so that
// the addresses of value maps stay constant. The qmake generators rely on that.
class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
{
public:
    inline void push(const ProValueMap &t) { append(t); }
    inline ProValueMap pop() { return takeLast(); }
    ProValueMap &top() { return last(); }
    const ProValueMap &top() const { return last(); }
};
105

106
107
108
class QMAKE_EXPORT QMakeEvaluator
{
public:
109
110
111
112
    enum LoadFlag {
        LoadProOnly = 0,
        LoadPreFiles = 1,
        LoadPostFiles = 2,
113
        LoadAll = LoadPreFiles|LoadPostFiles,
114
115
        LoadSilent = 0x10,
        LoadHidden = 0x20
116
117
118
    };
    Q_DECLARE_FLAGS(LoadFlags, LoadFlag)

119
    static void initStatics();
120
    static void initFunctionStatics();
121
    QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
122
                   QMakeHandler *handler);
123
124
    ~QMakeEvaluator();

125
126
    void setExtraVars(const ProValueMap &extraVars) { m_extraVars = extraVars; }
    void setExtraConfigs(const ProStringList &extraConfigs) { m_extraConfigs = extraConfigs; }
127
    void setOutputDir(const QString &outputDir) { m_outputDir = outputDir; }
128

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
129
130
131
132
    ProStringList values(const ProKey &variableName) const;
    ProStringList &valuesRef(const ProKey &variableName);
    ProString first(const ProKey &variableName) const;
    ProString propertyValue(const ProKey &val) const;
133

134
135
136
    ProString dirSep() const { return m_dirSep; }
    bool isHostBuild() const { return m_hostBuild; }

137
138
139
    enum VisitReturn {
        ReturnFalse,
        ReturnTrue,
140
        ReturnError,
141
142
143
144
145
146
147
148
149
150
151
152
153
154
        ReturnBreak,
        ReturnNext,
        ReturnReturn
    };

    static ALWAYS_INLINE VisitReturn returnBool(bool b)
        { return b ? ReturnTrue : ReturnFalse; }

    static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
    void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
    static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
    static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
    void skipExpression(const ushort *&tokPtr);

155
    void loadDefaults();
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
156
    bool prepareProject(const QString &inDir);
157
    bool loadSpecInternal();
158
    bool loadSpec();
159
    void initFrom(const QMakeEvaluator *other);
160
    void setupProject();
161
    void evaluateCommand(const QString &cmds, const QString &where);
162
    void applyExtraConfigs();
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
163
    VisitReturn visitProFile(ProFile *pro, QMakeHandler::EvalFileType type,
164
                             LoadFlags flags);
165
166
    VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
    VisitReturn visitProBlock(const ushort *tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
167
    VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr,
168
                             const ushort *tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
169
    void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr);
170
171
    void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
172
173
174
    ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); }
    const ProKey &map(const ProKey &var);
    ProValueMap *findValues(const ProKey &variableName, ProValueMap::Iterator *it);
175

176
177
    void setTemplate();

178
179
180
181
182
183
184
185
    ProStringList split_value_list(const QString &vals, const ProFile *source = 0);
    ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
    ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);

    QString currentFileName() const;
    QString currentDirectory() const;
    ProFile *currentProFile() const;
    QString resolvePath(const QString &fileName) const
186
        { return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
187

188
    VisitReturn evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
189
                             LoadFlags flags);
190
191
192
193
194
195
196
    VisitReturn evaluateFileChecked(const QString &fileName, QMakeHandler::EvalFileType type,
                                    LoadFlags flags);
    VisitReturn evaluateFeatureFile(const QString &fileName, bool silent = false);
    VisitReturn evaluateFileInto(const QString &fileName,
                                 ProValueMap *values, // output-only
                                 LoadFlags flags);
    VisitReturn evaluateConfigFeatures();
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
197
198
199
    void message(int type, const QString &msg) const;
    void evalError(const QString &msg) const
            { message(QMakeHandler::EvalError, msg); }
200
201
202
203
    void languageWarning(const QString &msg) const
            { message(QMakeHandler::EvalWarnLanguage, msg); }
    void deprecationWarning(const QString &msg) const
            { message(QMakeHandler::EvalWarnDeprecated, msg); }
204
205
206

    QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
    ProStringList evaluateFunction(const ProFunctionDef &func,
207
                                   const QList<ProStringList> &argumentsList, VisitReturn *ok);
208
209
210
211
    VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
                                     const QList<ProStringList> &argumentsList,
                                     const ProString &function);

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
212
213
    ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
    VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
214

215
216
    ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
    VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
217

218
    bool evaluateConditional(const QString &cond, const QString &where, int line = -1);
219
220
221
#ifdef PROEVALUATOR_FULL
    void checkRequirements(const ProStringList &deps);
#endif
222

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
223
    void updateMkspecPaths();
224
    void updateFeaturePaths();
225
226
227
228

    bool isActiveConfig(const QString &config, bool regex = false);

    void populateDeps(
229
            const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes,
230
231
232
            const ProString &priosfx,
            QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees,
            QMultiMap<int, ProString> &rootSet) const;
233

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
234
235
    VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
                          const QString &contents);
236
#ifndef QT_BOOTSTRAPPED
237
    void runProcess(QProcess *proc, const QString &command) const;
238
#endif
239
    QByteArray getCommandOutput(const QString &args) const;
240

241
    QMakeEvaluator *m_caller;
242
243
#ifdef PROEVALUATOR_CUMULATIVE
    bool m_cumulative;
244
    int m_skipLevel;
245
246
#else
    enum { m_cumulative = 0 };
247
    enum { m_skipLevel = 0 };
248
249
#endif

250
251
    static QString quoteValue(const ProString &val);

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#ifdef PROEVALUATOR_DEBUG
    void debugMsgInternal(int level, const char *fmt, ...) const;
    void traceMsgInternal(const char *fmt, ...) const;
    static QString formatValue(const ProString &val, bool forceQuote = false);
    static QString formatValueList(const ProStringList &vals, bool commas = false);
    static QString formatValueListList(const QList<ProStringList> &vals);

    const int m_debugLevel;
#else
    ALWAYS_INLINE void debugMsgInternal(int, const char *, ...) const {}
    ALWAYS_INLINE void traceMsgInternal(const char *, ...) const {}

    enum { m_debugLevel = 0 };
#endif

267
268
    struct Location {
        Location() : pro(0), line(0) {}
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
269
        Location(ProFile *_pro, ushort _line) : pro(_pro), line(_line) {}
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
270
        void clear() { pro = 0; line = 0; }
271
        ProFile *pro;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
272
        ushort line;
273
274
275
276
277
278
    };

    Location m_current; // Currently evaluated location
    QStack<Location> m_locationStack; // All execution location changes
    QStack<ProFile *> m_profileStack; // Includes only

279
280
    ProValueMap m_extraVars;
    ProStringList m_extraConfigs;
281
282
283
    QString m_outputDir;

    int m_listCount;
284
    bool m_valuemapInited;
285
    bool m_hostBuild;
286
287
    QString m_qmakespec;
    QString m_qmakespecName;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
288
    QString m_superfile;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
289
    QString m_conffile;
290
    QString m_cachefile;
291
    QString m_stashfile;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
292
    QString m_sourceRoot;
293
    QString m_buildRoot;
294
295
    QStringList m_qmakepath;
    QStringList m_qmakefeatures;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
296
    QStringList m_mkspecPaths;
297
    QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots;
298
    ProString m_dirSep;
299
300
    ProFunctionDefs m_functionDefs;
    ProStringList m_returnValue;
301
    ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
302
    QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
303
    mutable QString m_mtmp;
304
305
306

    QMakeGlobals *m_option;
    QMakeParser *m_parser;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
307
    QMakeHandler *m_handler;
308
    QMakeVfs *m_vfs;
309
};
Marc Mutz's avatar
Marc Mutz committed
310
Q_DECLARE_TYPEINFO(QMakeEvaluator::Location, Q_PRIMITIVE_TYPE);
311

312
313
Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeEvaluator::LoadFlags)

314
315
316
QT_END_NAMESPACE

#endif // QMAKEEVALUATOR_H