summaryrefslogtreecommitdiffstats
path: root/qmake/generators/makefile.h
blob: 3517e4f2d42344a54b8627671844756eb5f1521e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmake application of the Qt Toolkit.
**
** $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$
**
****************************************************************************/

#ifndef MAKEFILE_H
#define MAKEFILE_H

#include "option.h"
#include "project.h"
#include "makefiledeps.h"
#include <qtextstream.h>
#include <qlist.h>
#include <qhash.h>
#include <qfileinfo.h>

QT_BEGIN_NAMESPACE

#ifdef Q_OS_WIN32
#define QT_POPEN _popen
#define QT_PCLOSE _pclose
#else
#define QT_POPEN popen
#define QT_PCLOSE pclose
#endif

struct ReplaceExtraCompilerCacheKey;

class MakefileGenerator : protected QMakeSourceFileInfo
{
    QString spec;
    bool no_io;
    QHash<QString, bool> init_compiler_already;
    QString makedir, chkexists;
    QString build_args();

    //internal caches
    mutable QHash<QString, QMakeLocalFileName> depHeuristicsCache;
    mutable QHash<QString, QStringList> dependsCache;
    mutable QHash<ReplaceExtraCompilerCacheKey, QString> extraCompilerVariablesCache;

public:
    // We can't make it visible to VCFilter in VS2008 except by making it public or directly friending it.
    enum ReplaceFor { NoShell, LocalShell, TargetShell };

protected:
    enum TARG_MODE { TARG_UNIX_MODE, TARG_MAC_MODE, TARG_WIN_MODE } target_mode;

    ProStringList createObjectList(const ProStringList &sources);

    //makefile style generator functions
    void writeObj(QTextStream &, const char *src);
    void writeInstalls(QTextStream &t, bool noBuild=false);
    void writeHeader(QTextStream &t);
    void writeSubDirs(QTextStream &t);
    void writeMakeQmake(QTextStream &t, bool noDummyQmakeAll = false);
    void writeExtraVariables(QTextStream &t);
    void writeExtraTargets(QTextStream &t);
    void writeExtraCompilerTargets(QTextStream &t);
    void writeExtraCompilerVariables(QTextStream &t);
    bool writeDummyMakefile(QTextStream &t);
    virtual bool writeStubMakefile(QTextStream &t);
    virtual bool writeMakefile(QTextStream &t);
    virtual void writeDefaultVariables(QTextStream &t);

    QString pkgConfigPrefix() const;
    QString pkgConfigFileName(bool fixify=true);
    QString pkgConfigFixPath(QString) const;
    void writePkgConfigFile();   // for pkg-config

    //generating subtarget makefiles
    struct SubTarget
    {
        QString name;
        QString in_directory, out_directory;
        QString profile, target, makefile;
        ProStringList depends;
    };
    enum SubTargetFlags {
        SubTargetInstalls=0x01,
        SubTargetOrdered=0x02,
        SubTargetSkipDefaultVariables=0x04,
        SubTargetSkipDefaultTargets=0x08,

        SubTargetsNoFlags=0x00
    };
    QList<MakefileGenerator::SubTarget*> findSubDirsSubTargets() const;
    void writeSubTargetCall(QTextStream &t,
            const QString &in_directory, const QString &in, const QString &out_directory, const QString &out,
            const QString &out_directory_cdin, const QString &makefilein);
    virtual void writeSubMakeCall(QTextStream &t, const QString &outDirectory_cdin,
                                  const QString &makeFileIn);
    virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags);

    //extra compiler interface
    bool verifyExtraCompiler(const ProString &c, const QString &f);
    virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor forShell);
    inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out, ReplaceFor forShell)
    { return replaceExtraCompilerVariables(val, QStringList(in), QStringList(out), forShell); }

    //interface to the source file info
    QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool);
    QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &);
    QFileInfo findFileInfo(const QMakeLocalFileName &);
    QMakeProject *project;

    //escape
    virtual QString escapeFilePath(const QString &path) const { return path; }
    ProString escapeFilePath(const ProString &path) const;
    QStringList escapeFilePaths(const QStringList &paths) const;
    ProStringList escapeFilePaths(const ProStringList &paths) const;
    virtual QString escapeDependencyPath(const QString &path) const { return escapeFilePath(path); }
    ProString escapeDependencyPath(const ProString &path) const;
    QStringList escapeDependencyPaths(const QStringList &paths) const;
    ProStringList escapeDependencyPaths(const ProStringList &paths) const;

    //initialization
    void verifyCompilers();
    virtual void init();
    void initOutPaths();
    struct Compiler
    {
        QString variable_in;
        enum CompilerFlag {
            CompilerNoFlags                 = 0x00,
            CompilerBuiltin                 = 0x01,
            CompilerNoCheckDeps             = 0x02,
            CompilerRemoveNoExist           = 0x04,
            CompilerAddInputsAsMakefileDeps = 0x08
        };
        uint flags, type;
    };
    void initCompiler(const Compiler &comp);
    enum VPATHFlag {
        VPATH_NoFlag             = 0x00,
        VPATH_WarnMissingFiles   = 0x01,
        VPATH_RemoveMissingFiles = 0x02,
        VPATH_NoFixify           = 0x04
    };
    ProStringList findFilesInVPATH(ProStringList l, uchar flags, const QString &var="");

    inline int findExecutable(const QStringList &cmdline)
    { int ret; canExecute(cmdline, &ret); return ret; }
    bool canExecute(const QStringList &cmdline, int *argv0) const;
    inline bool canExecute(const QString &cmdline) const
    { return canExecute(cmdline.split(' '), 0); }

    bool mkdir(const QString &dir) const;
    QString mkdir_p_asstring(const QString &dir, bool escape=true) const;

    QString specdir();

    //subclasses can use these to query information about how the generator was "run"
    QString buildArgs();

    virtual QStringList &findDependencies(const QString &file);
    virtual bool doDepends() const { return Option::mkfile::do_deps; }

    void filterIncludedFiles(const char *);
    void processSources() {
        filterIncludedFiles("SOURCES");
        filterIncludedFiles("GENERATED_SOURCES");
    }

    //for installs
    virtual QString defaultInstall(const QString &);

    //for prl
    QString prlFileName(bool fixify=true);
    void writePrlFile();
    bool processPrlFile(QString &);
    virtual void writePrlFile(QTextStream &);

    //make sure libraries are found
    virtual bool findLibraries(bool linkPrl, bool mergeLflags);

    //for retrieving values and lists of values
    virtual QString var(const ProKey &var) const;
    QString varGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
    QString varList(const ProKey &var) const;
    QString fixFileVarGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
    QString fileVarList(const ProKey &var) const;
    QString fileVarGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
    QString fileVar(const ProKey &var) const;
    QString depVar(const ProKey &var) const;
    QString val(const ProStringList &varList) const;
    QString val(const QStringList &varList) const;
    QString valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after) const;
    QString valGlue(const ProStringList &varList, const QString &before, const QString &glue, const QString &after) const;
    QString valList(const QStringList &varList) const;
    QString valList(const ProStringList &varList) const;

    QString filePrefixRoot(const QString &, const QString &);

    enum LibFlagType { LibFlagLib, LibFlagPath, LibFlagFile, LibFlagOther };
    virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg);
    ProStringList fixLibFlags(const ProKey &var);
    virtual ProString fixLibFlag(const ProString &lib);

public:
    //file fixification to unify all file names into a single pattern
    enum FileFixifyType {
        FileFixifyFromIndir = 0,
        FileFixifyFromOutdir = 1,
        FileFixifyToOutDir = 0,
        FileFixifyToIndir = 2,
        FileFixifyBackwards = FileFixifyFromOutdir | FileFixifyToIndir,
        FileFixifyDefault = 0,
        FileFixifyAbsolute = 4,
        FileFixifyRelative = 8
    };
    Q_DECLARE_FLAGS(FileFixifyTypes, FileFixifyType)
protected:
    QString fileFixify(const QString &file, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;
    QStringList fileFixify(const QStringList &files, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;

    QString installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst);

public:
    MakefileGenerator();
    virtual ~MakefileGenerator();
    QMakeProject *projectFile() const;
    void setProjectFile(QMakeProject *p);

    void setNoIO(bool o);
    bool noIO() const;

    inline bool exists(QString file) const { return fileInfo(file).exists(); }
    QFileInfo fileInfo(QString file) const;

    static MakefileGenerator *create(QMakeProject *);
    virtual bool write();
    virtual bool writeProjectMakefile();
    virtual bool supportsMetaBuild() { return true; }
    virtual bool supportsMergedBuilds() { return false; }
    virtual bool mergeBuildProject(MakefileGenerator * /*other*/) { return false; }
    virtual bool openOutput(QFile &, const QString &build) const;
    bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
    QString shellQuote(const QString &str);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)

inline void MakefileGenerator::setNoIO(bool o)
{ no_io = o; }

inline bool MakefileGenerator::noIO() const
{ return no_io; }

inline QString MakefileGenerator::defaultInstall(const QString &)
{ return QString(""); }

inline bool MakefileGenerator::findLibraries(bool, bool)
{ return true; }

inline MakefileGenerator::~MakefileGenerator()
{ }

struct ReplaceExtraCompilerCacheKey
{
    mutable uint hash;
    QString var, in, out, pwd;
    MakefileGenerator::ReplaceFor forShell;
    ReplaceExtraCompilerCacheKey(const QString &v, const QStringList &i, const QStringList &o, MakefileGenerator::ReplaceFor s);
    bool operator==(const ReplaceExtraCompilerCacheKey &f) const;
    inline uint hashCode() const {
        if (!hash)
            hash = (uint)forShell ^ qHash(var) ^ qHash(in) ^ qHash(out) /*^ qHash(pwd)*/;
        return hash;
    }
};
inline uint qHash(const ReplaceExtraCompilerCacheKey &f) { return f.hashCode(); }

QT_END_NAMESPACE

#endif // MAKEFILE_H