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