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#ifndef MAKEFILE_H
5#define MAKEFILE_H
6
7#include "option.h"
8#include "project.h"
9#include "makefiledeps.h"
10#include <qtextstream.h>
11#include <qlist.h>
12#include <qhash.h>
13#include <qfileinfo.h>
14#include <functional>
15
16QT_BEGIN_NAMESPACE
17
18#ifdef Q_OS_WIN32
19#define QT_POPEN _popen
20#define QT_POPEN_READ "rb"
21#define QT_PCLOSE _pclose
22#else
23#define QT_POPEN popen
24#define QT_POPEN_READ "r"
25#define QT_PCLOSE pclose
26#endif
27
28struct ReplaceExtraCompilerCacheKey;
29
30class MakefileGenerator : protected QMakeSourceFileInfo
31{
32 QString spec;
33 bool no_io = false;
34 bool resolveDependenciesInFrameworks = false;
35 QHash<QString, bool> init_compiler_already;
36 QString makedir, chkexists;
37 QString fullBuildArgs();
38
39 //internal caches
40 mutable QHash<QString, QMakeLocalFileName> depHeuristicsCache;
41 mutable QHash<QString, QStringList> dependsCache;
42 mutable QHash<ReplaceExtraCompilerCacheKey, QString> extraCompilerVariablesCache;
43
44public:
45 // We can't make it visible to VCFilter in VS2008 except by making it public or directly friending it.
46 enum ReplaceFor { NoShell, LocalShell, TargetShell };
47
48protected:
49 enum TARG_MODE { TARG_UNIX_MODE, TARG_MAC_MODE, TARG_WIN_MODE } target_mode;
50
51 ProStringList createObjectList(const ProStringList &sources);
52
53 //makefile style generator functions
54 void writeObj(QTextStream &, const char *src);
55 void writeInstalls(QTextStream &t, bool noBuild=false);
56 void writeHeader(QTextStream &t);
57 void writeSubDirs(QTextStream &t);
58 void writeMakeQmake(QTextStream &t, bool noDummyQmakeAll = false);
59 void writeExportedVariables(QTextStream &t);
60 void writeExtraVariables(QTextStream &t);
61 void writeExtraTargets(QTextStream &t);
62 QString resolveDependency(const QDir &outDir, const QString &file);
63 void callExtraCompilerDependCommand(const ProString &extraCompiler,
64 const QString &tmp_dep_cmd, const QString &inpf,
65 const QString &tmp_out, bool dep_lines, QStringList *deps,
66 bool existingDepsOnly,
67 bool checkCommandAvailability = false);
68 void writeExtraCompilerTargets(QTextStream &t);
69 void writeExtraCompilerVariables(QTextStream &t);
70 bool writeDummyMakefile(QTextStream &t);
71 virtual bool writeMakefile(QTextStream &t);
72 virtual void writeDefaultVariables(QTextStream &t);
73
74 QString pkgConfigPrefix() const;
75 QString pkgConfigFileName(bool fixify=true);
76 QString pkgConfigFixPath(QString) const;
77 void writePkgConfigFile(); // for pkg-config
78
79 //generating subtarget makefiles
80 struct SubTarget
81 {
82 QString name;
83 QString in_directory, out_directory;
84 QString profile, target, makefile;
85 ProStringList depends;
86 };
87 enum SubTargetFlags {
88 SubTargetInstalls=0x01,
89 SubTargetOrdered=0x02,
90 SubTargetSkipDefaultVariables=0x04,
91 SubTargetSkipDefaultTargets=0x08,
92
93 SubTargetsNoFlags=0x00
94 };
95 QList<MakefileGenerator::SubTarget*> findSubDirsSubTargets() const;
96 void writeSubTargetCall(QTextStream &t,
97 const QString &in_directory, const QString &in, const QString &out_directory, const QString &out,
98 const QString &out_directory_cdin, const QString &makefilein);
99 virtual void suppressBuiltinRules(QTextStream &t) const;
100 virtual void writeSubMakeCall(QTextStream &t, const QString &outDirectory_cdin,
101 const QString &makeFileIn);
102 virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags);
103 virtual ProStringList extraSubTargetDependencies() { return {}; }
104
105 //extra compiler interface
106 bool verifyExtraCompiler(const ProString &c, const QString &f);
107 virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor forShell);
108 inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out, ReplaceFor forShell)
109 { return replaceExtraCompilerVariables(val, QStringList(in), QStringList(out), forShell); }
110
111 //interface to the source file info
112 QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool) override;
113 QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &) override;
114 QFileInfo findFileInfo(const QMakeLocalFileName &) override;
115 QMakeProject *project = nullptr;
116
117 //escape
118 virtual QString escapeFilePath(const QString &path) const = 0;
119 ProString escapeFilePath(const ProString &path) const;
120 template<typename A, typename B>
121 QString escapeFilePath(const QStringBuilder<A, B> &path) const
122 { return escapeFilePath(path: QString(path)); }
123 QStringList escapeFilePaths(const QStringList &paths) const;
124 ProStringList escapeFilePaths(const ProStringList &paths) const;
125 virtual QString escapeDependencyPath(const QString &path) const;
126 ProString escapeDependencyPath(const ProString &path) const;
127 template<typename A, typename B>
128 QString escapeDependencyPath(const QStringBuilder<A, B> &path) const
129 { return escapeDependencyPath(path: QString(path)); }
130 QStringList escapeDependencyPaths(const QStringList &paths) const;
131 ProStringList escapeDependencyPaths(const ProStringList &paths) const;
132
133 QStringList finalizeDependencyPaths(const QStringList &paths) const;
134
135 //initialization
136 void verifyCompilers();
137 virtual void init();
138 void initOutPaths();
139 virtual bool inhibitMakeDirOutPath(const ProKey &path) const;
140 struct Compiler
141 {
142 QString variable_in;
143 enum CompilerFlag {
144 CompilerNoFlags = 0x00,
145 CompilerBuiltin = 0x01,
146 CompilerNoCheckDeps = 0x02,
147 CompilerRemoveNoExist = 0x04,
148 CompilerWarnNoExist = 0x08,
149 CompilerAddInputsAsMakefileDeps = 0x10
150 };
151 uint flags, type;
152 };
153 friend class QTypeInfo<Compiler>;
154
155 void initCompiler(const Compiler &comp);
156 enum VPATHFlag {
157 VPATH_NoFlag = 0x00,
158 VPATH_WarnMissingFiles = 0x01,
159 VPATH_RemoveMissingFiles = 0x02,
160 VPATH_NoFixify = 0x04
161 };
162 ProStringList findFilesInVPATH(ProStringList l, uchar flags, const QString &var="");
163
164 inline int findExecutable(const QStringList &cmdline)
165 { int ret; canExecute(cmdline, argv0: &ret); return ret; }
166 bool canExecute(const QStringList &cmdline, int *argv0) const;
167 inline bool canExecute(const QString &cmdline) const
168 { return canExecute(cmdline: cmdline.split(sep: ' '), argv0: nullptr); }
169
170 bool mkdir(const QString &dir) const;
171 QString mkdir_p_asstring(const QString &dir, bool escape=true) const;
172
173 QString specdir();
174
175 //subclasses can use these to query information about how the generator was "run"
176 QString buildArgs(bool withExtra);
177
178 virtual QStringList &findDependencies(const QString &file);
179 virtual bool doDepends() const { return Option::mkfile::do_deps; }
180
181 void filterIncludedFiles(const char *);
182 void processSources();
183
184 //for installs
185 virtual QString defaultInstall(const QString &);
186 virtual QString installRoot() const;
187
188 //for prl
189 QString prlFileName(bool fixify=true);
190 void writePrlFile();
191 bool processPrlFile(QString &, bool baseOnly);
192 virtual void writePrlFile(QTextStream &);
193
194 //make sure libraries are found
195 virtual bool findLibraries(bool linkPrl, bool mergeLflags);
196
197 //for retrieving values and lists of values
198 virtual QString var(const ProKey &var) const;
199 QString varGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
200 QString varList(const ProKey &var) const;
201 QString fixFileVarGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
202 QString fileVarList(const ProKey &var) const;
203 QString fileVarGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after) const;
204 QString fileVar(const ProKey &var) const;
205 QString depVar(const ProKey &var) const;
206 QString val(const ProStringList &varList) const;
207 QString val(const QStringList &varList) const;
208 QString valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after) const;
209 QString valGlue(const ProStringList &varList, const QString &before, const QString &glue, const QString &after) const;
210 QString valList(const QStringList &varList) const;
211 QString valList(const ProStringList &varList) const;
212
213 QString filePrefixRoot(const QString &, const QString &);
214
215 enum LibFlagType { LibFlagLib, LibFlagPath, LibFlagFile, LibFlagOther };
216 virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg);
217 ProStringList fixLibFlags(const ProKey &var);
218 virtual ProString fixLibFlag(const ProString &lib);
219
220public:
221 //file fixification to unify all file names into a single pattern
222 enum FileFixifyType {
223 FileFixifyFromIndir = 0,
224 FileFixifyFromOutdir = 1,
225 FileFixifyToOutDir = 0,
226 FileFixifyToIndir = 2,
227 FileFixifyBackwards = FileFixifyFromOutdir | FileFixifyToIndir,
228 FileFixifyDefault = 0,
229 FileFixifyAbsolute = 4,
230 FileFixifyRelative = 8
231 };
232 Q_DECLARE_FLAGS(FileFixifyTypes, FileFixifyType)
233protected:
234 QString fileFixify(const QString &file, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;
235 QStringList fileFixify(const QStringList &files, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;
236 QString createSedArgs(const ProKey &replace_rule, const QString &file_type = QString()) const;
237 QString installMetaFile(const ProKey &replace_rule, const QString &src,
238 const QString &dst) const;
239
240 virtual bool processPrlFileBase(QString &origFile, QStringView origName,
241 QStringView fixedBase, int slashOff);
242 bool processPrlFileCore(QString &origFile, QStringView origName,
243 const QString &fixedFile);
244 QString createResponseFile(const QString &baseName,
245 const ProStringList &objList,
246 const QString &prefix = QString()) const;
247
248 struct LinkerResponseFileInfo
249 {
250 QString filePath;
251 bool onlyObjects;
252
253 bool isValid() const { return !filePath.isEmpty(); }
254 };
255
256 LinkerResponseFileInfo maybeCreateLinkerResponseFile() const;
257
258public:
259 QMakeProject *projectFile() const;
260 void setProjectFile(QMakeProject *p);
261
262 void setNoIO(bool o);
263 bool noIO() const;
264
265 inline bool exists(QString file) const { return fileInfo(file).exists(); }
266 QFileInfo fileInfo(QString file) const;
267
268 static MakefileGenerator *create(QMakeProject *);
269 virtual bool write();
270 virtual bool writeProjectMakefile();
271 virtual bool supportsMetaBuild() { return true; }
272 virtual bool supportsMergedBuilds() { return false; }
273 virtual bool mergeBuildProject(MakefileGenerator * /*other*/) { return false; }
274 virtual bool openOutput(QFile &, const QString &build) const;
275 bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
276 QString shellQuote(const QString &str) const;
277 virtual ProKey fullTargetVariable() const;
278};
279Q_DECLARE_TYPEINFO(MakefileGenerator::Compiler, Q_RELOCATABLE_TYPE);
280Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)
281
282inline void MakefileGenerator::setNoIO(bool o)
283{ no_io = o; }
284
285inline bool MakefileGenerator::noIO() const
286{ return no_io; }
287
288inline QString MakefileGenerator::defaultInstall(const QString &)
289{ return QString(""); }
290
291inline QString MakefileGenerator::installRoot() const
292{ return QStringLiteral("$(INSTALL_ROOT)"); }
293
294inline bool MakefileGenerator::findLibraries(bool, bool)
295{ return true; }
296
297struct ReplaceExtraCompilerCacheKey
298{
299 mutable size_t hash;
300 QString var, in, out, pwd;
301 MakefileGenerator::ReplaceFor forShell;
302 ReplaceExtraCompilerCacheKey(const QString &v, const QStringList &i, const QStringList &o, MakefileGenerator::ReplaceFor s);
303 bool operator==(const ReplaceExtraCompilerCacheKey &f) const;
304 inline size_t hashCode() const {
305 if (!hash)
306 hash = (size_t)forShell ^ qHash(key: var) ^ qHash(key: in) ^ qHash(key: out) /*^ qHash(pwd)*/;
307 return hash;
308 }
309};
310inline size_t qHash(const ReplaceExtraCompilerCacheKey &f) { return f.hashCode(); }
311
312QT_END_NAMESPACE
313
314#endif // MAKEFILE_H
315

source code of qtbase/qmake/generators/makefile.h