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 #include "option.h"
30 #include "cachekeys.h"
31 #include <ioutils.h>
32 #include <qdir.h>
33 #include <qregexp.h>
34 #include <qhash.h>
35 #include <qdebug.h>
36 #include <qlibraryinfo.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39
40 QT_BEGIN_NAMESPACE
41
42 using namespace QMakeInternal;
43
44 EvalHandler Option::evalHandler;
45 QMakeGlobals *Option::globals;
46 ProFileCache *Option::proFileCache;
47 QMakeVfs *Option::vfs;
48 QMakeParser *Option::parser;
49
50 //convenience
51 QString Option::prf_ext;
52 QString Option::prl_ext;
53 QString Option::libtool_ext;
54 QString Option::pkgcfg_ext;
55 QString Option::ui_ext;
56 QStringList Option::h_ext;
57 QString Option::cpp_moc_ext;
58 QStringList Option::cpp_ext;
59 QStringList Option::c_ext;
60 QString Option::objc_ext;
61 QString Option::objcpp_ext;
62 QString Option::obj_ext;
63 QString Option::lex_ext;
64 QString Option::yacc_ext;
65 QString Option::pro_ext;
66 QString Option::dir_sep;
67 QString Option::h_moc_mod;
68 QString Option::yacc_mod;
69 QString Option::lex_mod;
70 QString Option::res_ext;
71 char Option::field_sep;
72
73 //mode
74 Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
75
76 //all modes
77 int Option::warn_level = WarnLogic | WarnDeprecated;
78 int Option::debug_level = 0;
79 QFile Option::output;
80 QString Option::output_dir;
81 bool Option::recursive = false;
82
83 //QMAKE_*_PROPERTY stuff
84 QStringList Option::prop::properties;
85
86 //QMAKE_GENERATE_PROJECT stuff
87 bool Option::projfile::do_pwd = true;
88 QStringList Option::projfile::project_dirs;
89
90 //QMAKE_GENERATE_MAKEFILE stuff
91 int Option::mkfile::cachefile_depth = -1;
92 bool Option::mkfile::do_deps = true;
93 bool Option::mkfile::do_mocs = true;
94 bool Option::mkfile::do_dep_heuristics = true;
95 bool Option::mkfile::do_preprocess = false;
96 QStringList Option::mkfile::project_files;
97
default_mode(QString progname)98 static Option::QMAKE_MODE default_mode(QString progname)
99 {
100 int s = progname.lastIndexOf(QDir::separator());
101 if(s != -1)
102 progname = progname.right(progname.length() - (s + 1));
103 if(progname == "qmakegen")
104 return Option::QMAKE_GENERATE_PROJECT;
105 else if(progname == "qt-config")
106 return Option::QMAKE_QUERY_PROPERTY;
107 return Option::QMAKE_GENERATE_MAKEFILE;
108 }
109
detectProjectFile(const QString & path)110 static QString detectProjectFile(const QString &path)
111 {
112 QString ret;
113 QDir dir(path);
114 if(dir.exists(dir.dirName() + Option::pro_ext)) {
115 ret = dir.filePath(dir.dirName()) + Option::pro_ext;
116 } else { //last try..
117 QStringList profiles = dir.entryList(QStringList("*" + Option::pro_ext));
118 if(profiles.count() == 1)
119 ret = dir.filePath(profiles.at(0));
120 }
121 return ret;
122 }
123
usage(const char * a0)124 bool usage(const char *a0)
125 {
126 fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
127 "\n"
128 "QMake has two modes, one mode for generating project files based on\n"
129 "some heuristics, and the other for generating makefiles. Normally you\n"
130 "shouldn't need to specify a mode, as makefile generation is the default\n"
131 "mode for qmake, but you may use this to test qmake on an existing project\n"
132 "\n"
133 "Mode:\n"
134 " -project Put qmake into project file generation mode%s\n"
135 " In this mode qmake interprets [files] as files to\n"
136 " be added to the .pro file. By default, all files with\n"
137 " known source extensions are added.\n"
138 " Note: The created .pro file probably will \n"
139 " need to be edited. For example add the QT variable to \n"
140 " specify what modules are required.\n"
141 " -makefile Put qmake into makefile generation mode%s\n"
142 " In this mode qmake interprets files as project files to\n"
143 " be processed, if skipped qmake will try to find a project\n"
144 " file in your current working directory\n"
145 "\n"
146 "Warnings Options:\n"
147 " -Wnone Turn off all warnings; specific ones may be re-enabled by\n"
148 " later -W options\n"
149 " -Wall Turn on all warnings\n"
150 " -Wparser Turn on parser warnings\n"
151 " -Wlogic Turn on logic warnings (on by default)\n"
152 " -Wdeprecated Turn on deprecation warnings (on by default)\n"
153 "\n"
154 "Options:\n"
155 " * You can place any variable assignment in options and it will be *\n"
156 " * processed as if it was in [files]. These assignments will be *\n"
157 " * processed before [files] by default. *\n"
158 " -o file Write output to file\n"
159 " -d Increase debug level\n"
160 " -t templ Overrides TEMPLATE as templ\n"
161 " -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
162 " -help This help\n"
163 " -v Version information\n"
164 " -early All subsequent variable assignments will be\n"
165 " parsed right before default_pre.prf\n"
166 " -before All subsequent variable assignments will be\n"
167 " parsed right before [files] (the default)\n"
168 " -after All subsequent variable assignments will be\n"
169 " parsed after [files]\n"
170 " -late All subsequent variable assignments will be\n"
171 " parsed right after default_post.prf\n"
172 " -norecursive Don't do a recursive search\n"
173 " -recursive Do a recursive search\n"
174 " -set <prop> <value> Set persistent property\n"
175 " -unset <prop> Unset persistent property\n"
176 " -query <prop> Query persistent property. Show all if <prop> is empty.\n"
177 " -qtconf file Use file instead of looking for qt.conf\n"
178 " -cache file Use file as cache [makefile mode only]\n"
179 " -spec spec Use spec as QMAKESPEC [makefile mode only]\n"
180 " -nocache Don't use a cache file [makefile mode only]\n"
181 " -nodepend Don't generate dependencies [makefile mode only]\n"
182 " -nomoc Don't generate moc targets [makefile mode only]\n"
183 " -nopwd Don't look for files in pwd [project mode only]\n"
184 ,a0,
185 default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "",
186 default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
187 );
188 return false;
189 }
190
191 int
parseCommandLine(QStringList & args,QMakeCmdLineParserState & state)192 Option::parseCommandLine(QStringList &args, QMakeCmdLineParserState &state)
193 {
194 enum { ArgNone, ArgOutput } argState = ArgNone;
195 int x = 0;
196 while (x < args.count()) {
197 switch (argState) {
198 case ArgOutput:
199 Option::output.setFileName(args.at(x--));
200 args.erase(args.begin() + x, args.begin() + x + 2);
201 argState = ArgNone;
202 continue;
203 default:
204 QMakeGlobals::ArgumentReturn cmdRet = globals->addCommandLineArguments(state, args, &x);
205 if (cmdRet == QMakeGlobals::ArgumentsOk)
206 break;
207 if (cmdRet == QMakeGlobals::ArgumentMalformed) {
208 fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
209 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
210 }
211 Q_ASSERT(cmdRet == QMakeGlobals::ArgumentUnknown);
212 QString arg = args.at(x);
213 if (arg.startsWith(QLatin1Char('-'))) {
214 if (arg == "-d") {
215 Option::debug_level++;
216 } else if (arg == "-v" || arg == "-version" || arg == "--version") {
217 fprintf(stdout,
218 "QMake version %s\n"
219 "Using Qt version %s in %s\n",
220 QMAKE_VERSION_STR, QT_VERSION_STR,
221 QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
222 #ifdef QMAKE_OPENSOURCE_VERSION
223 fprintf(stdout, "QMake is Open Source software from The Qt Company Ltd and/or its subsidiary(-ies).\n");
224 #endif
225 return Option::QMAKE_CMDLINE_BAIL;
226 } else if (arg == "-h" || arg == "-help" || arg == "--help") {
227 return Option::QMAKE_CMDLINE_SHOW_USAGE;
228 } else if (arg == "-Wall") {
229 Option::warn_level |= WarnAll;
230 } else if (arg == "-Wparser") {
231 Option::warn_level |= WarnParser;
232 } else if (arg == "-Wlogic") {
233 Option::warn_level |= WarnLogic;
234 } else if (arg == "-Wdeprecated") {
235 Option::warn_level |= WarnDeprecated;
236 } else if (arg == "-Wnone") {
237 Option::warn_level = WarnNone;
238 } else if (arg == "-r" || arg == "-recursive") {
239 Option::recursive = true;
240 args.removeAt(x);
241 continue;
242 } else if (arg == "-nr" || arg == "-norecursive") {
243 Option::recursive = false;
244 args.removeAt(x);
245 continue;
246 } else if (arg == "-o" || arg == "-output") {
247 argState = ArgOutput;
248 } else {
249 if (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
250 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
251 if (arg == "-nodepend" || arg == "-nodepends") {
252 Option::mkfile::do_deps = false;
253 } else if (arg == "-nomoc") {
254 Option::mkfile::do_mocs = false;
255 } else if (arg == "-nodependheuristics") {
256 Option::mkfile::do_dep_heuristics = false;
257 } else if (arg == "-E") {
258 Option::mkfile::do_preprocess = true;
259 } else {
260 fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
261 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
262 }
263 } else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
264 if (arg == "-nopwd") {
265 Option::projfile::do_pwd = false;
266 } else {
267 fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
268 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
269 }
270 }
271 }
272 } else {
273 bool handled = true;
274 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
275 Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
276 Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) {
277 Option::prop::properties.append(arg);
278 } else {
279 QFileInfo fi(arg);
280 if(!fi.makeAbsolute()) //strange
281 arg = fi.filePath();
282 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
283 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
284 if(fi.isDir()) {
285 QString proj = detectProjectFile(arg);
286 if (!proj.isNull())
287 arg = proj;
288 }
289 Option::mkfile::project_files.append(arg);
290 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
291 Option::projfile::project_dirs.append(arg);
292 } else {
293 handled = false;
294 }
295 }
296 if(!handled) {
297 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
298 }
299 args.removeAt(x);
300 continue;
301 }
302 }
303 x++;
304 }
305 if (argState != ArgNone) {
306 fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
307 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
308 }
309 return Option::QMAKE_CMDLINE_SUCCESS;
310 }
311
312 int
init(int argc,char ** argv)313 Option::init(int argc, char **argv)
314 {
315 Option::prf_ext = ".prf";
316 Option::pro_ext = ".pro";
317 Option::field_sep = ' ';
318
319 if(argc && argv) {
320 QString argv0 = argv[0];
321 #ifdef Q_OS_WIN
322 if (!argv0.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive))
323 argv0 += QLatin1String(".exe");
324 #endif
325 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
326 Option::qmake_mode = default_mode(argv0);
327 if (!argv0.isEmpty() && IoUtils::isAbsolutePath(argv0)) {
328 globals->qmake_abslocation = argv0;
329 } else if (argv0.contains(QLatin1Char('/'))
330 #ifdef Q_OS_WIN
331 || argv0.contains(QLatin1Char('\\'))
332 #endif
333 ) { //relative PWD
334 globals->qmake_abslocation = QDir::current().absoluteFilePath(argv0);
335 } else { //in the PATH
336 QByteArray pEnv = qgetenv("PATH");
337 QDir currentDir = QDir::current();
338 #ifdef Q_OS_WIN
339 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
340 paths.prepend(QLatin1String("."));
341 #else
342 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
343 #endif
344 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
345 if ((*p).isEmpty())
346 continue;
347 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
348 if (QFile::exists(candidate)) {
349 globals->qmake_abslocation = candidate;
350 break;
351 }
352 }
353 }
354 if (Q_UNLIKELY(globals->qmake_abslocation.isNull())) {
355 // This is rather unlikely to ever happen on a modern system ...
356 globals->qmake_abslocation = QLibraryInfo::rawLocation(
357 QLibraryInfo::HostBinariesPath,
358 QLibraryInfo::EffectivePaths)
359 #ifdef Q_OS_WIN
360 + "/qmake.exe";
361 #else
362 + "/qmake";
363 #endif
364 } else {
365 globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation);
366 }
367 } else {
368 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
369 }
370
371 QMakeCmdLineParserState cmdstate(QDir::currentPath());
372 const QByteArray envflags = qgetenv("QMAKEFLAGS");
373 if (!envflags.isNull()) {
374 QStringList args;
375 QByteArray buf = "";
376 char quote = 0;
377 bool hasWord = false;
378 for (int i = 0; i < envflags.size(); ++i) {
379 char c = envflags.at(i);
380 if (!quote && (c == '\'' || c == '"')) {
381 quote = c;
382 } else if (c == quote) {
383 quote = 0;
384 } else if (!quote && c == ' ') {
385 if (hasWord) {
386 args << QString::fromLocal8Bit(buf);
387 hasWord = false;
388 buf = "";
389 }
390 } else {
391 buf += c;
392 hasWord = true;
393 }
394 }
395 if (hasWord)
396 args << QString::fromLocal8Bit(buf);
397 parseCommandLine(args, cmdstate);
398 cmdstate.flush();
399 }
400 if(argc && argv) {
401 QStringList args;
402 args.reserve(argc - 1);
403 for (int i = 1; i < argc; i++)
404 args << QString::fromLocal8Bit(argv[i]);
405
406 while (!args.isEmpty()) {
407 QString opt = args.at(0);
408 if (opt == "-project") {
409 Option::recursive = true;
410 Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
411 } else if (opt == "-prl") {
412 Option::mkfile::do_deps = false;
413 Option::mkfile::do_mocs = false;
414 Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
415 } else if (opt == "-set") {
416 Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
417 } else if (opt == "-unset") {
418 Option::qmake_mode = Option::QMAKE_UNSET_PROPERTY;
419 } else if (opt == "-query") {
420 Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
421 } else if (opt == "-makefile") {
422 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
423 } else {
424 break;
425 }
426 args.takeFirst();
427 break;
428 }
429
430 int ret = parseCommandLine(args, cmdstate);
431 if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
432 if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
433 usage(argv[0]);
434 return ret;
435 //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
436 }
437 globals->qmake_args = args;
438 globals->qmake_extra_args = cmdstate.extraargs;
439 }
440 globals->commitCommandLineArguments(cmdstate);
441 globals->debugLevel = Option::debug_level;
442
443 //last chance for defaults
444 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
445 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
446 globals->useEnvironment();
447
448 //try REALLY hard to do it for them, lazy..
449 if(Option::mkfile::project_files.isEmpty()) {
450 QString proj = detectProjectFile(qmake_getpwd());
451 if(!proj.isNull())
452 Option::mkfile::project_files.append(proj);
453 #ifndef QT_BUILD_QMAKE_LIBRARY
454 if(Option::mkfile::project_files.isEmpty()) {
455 usage(argv[0]);
456 return Option::QMAKE_CMDLINE_ERROR;
457 }
458 #endif
459 }
460 }
461
462 return QMAKE_CMDLINE_SUCCESS;
463 }
464
prepareProject(const QString & pfile)465 void Option::prepareProject(const QString &pfile)
466 {
467 // Canonicalize only the directory, otherwise things will go haywire
468 // if the file itself is a symbolic link.
469 const QString srcpath = QFileInfo(QFileInfo(pfile).absolutePath()).canonicalFilePath();
470 globals->setDirectories(srcpath, output_dir);
471 }
472
postProcessProject(QMakeProject * project)473 bool Option::postProcessProject(QMakeProject *project)
474 {
475 Option::cpp_ext = project->values("QMAKE_EXT_CPP").toQStringList();
476 Option::h_ext = project->values("QMAKE_EXT_H").toQStringList();
477 Option::c_ext = project->values("QMAKE_EXT_C").toQStringList();
478 Option::objc_ext = project->first("QMAKE_EXT_OBJC").toQString();
479 Option::objcpp_ext = project->first("QMAKE_EXT_OBJCXX").toQString();
480 Option::res_ext = project->first("QMAKE_EXT_RES").toQString();
481 Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG").toQString();
482 Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL").toQString();
483 Option::prl_ext = project->first("QMAKE_EXT_PRL").toQString();
484 Option::ui_ext = project->first("QMAKE_EXT_UI").toQString();
485 Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC").toQString();
486 Option::lex_ext = project->first("QMAKE_EXT_LEX").toQString();
487 Option::yacc_ext = project->first("QMAKE_EXT_YACC").toQString();
488 Option::obj_ext = project->first("QMAKE_EXT_OBJ").toQString();
489 Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC").toQString();
490 Option::lex_mod = project->first("QMAKE_MOD_LEX").toQString();
491 Option::yacc_mod = project->first("QMAKE_MOD_YACC").toQString();
492
493 Option::dir_sep = project->dirSep().toQString();
494
495 if (!project->buildRoot().isEmpty() && Option::output_dir.startsWith(project->buildRoot()))
496 Option::mkfile::cachefile_depth =
497 Option::output_dir.mid(project->buildRoot().length()).count('/');
498
499 return true;
500 }
501
502 QString
fixString(QString string,uchar flags)503 Option::fixString(QString string, uchar flags)
504 {
505 //const QString orig_string = string;
506 static QHash<FixStringCacheKey, QString> *cache = nullptr;
507 if(!cache) {
508 cache = new QHash<FixStringCacheKey, QString>;
509 qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache);
510 }
511 FixStringCacheKey cacheKey(string, flags);
512
513 QHash<FixStringCacheKey, QString>::const_iterator it = cache->constFind(cacheKey);
514
515 if (it != cache->constEnd()) {
516 //qDebug() << "Fix (cached) " << orig_string << "->" << it.value();
517 return it.value();
518 }
519
520 //fix the environment variables
521 if(flags & Option::FixEnvVars) {
522 int rep;
523 static QRegExp reg_var("\\$\\(.*\\)");
524 reg_var.setMinimal(true);
525 while((rep = reg_var.indexIn(string)) != -1)
526 string.replace(rep, reg_var.matchedLength(),
527 QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
528 }
529
530 //canonicalize it (and treat as a path)
531 if(flags & Option::FixPathCanonicalize) {
532 #if 0
533 string = QFileInfo(string).canonicalFilePath();
534 #endif
535 string = QDir::cleanPath(string);
536 }
537
538 // either none or only one active flag
539 Q_ASSERT(((flags & Option::FixPathToLocalSeparators) != 0) +
540 ((flags & Option::FixPathToTargetSeparators) != 0) +
541 ((flags & Option::FixPathToNormalSeparators) != 0) <= 1);
542
543 //fix separators
544 if (flags & Option::FixPathToNormalSeparators) {
545 string.replace('\\', '/');
546 } else if (flags & Option::FixPathToLocalSeparators) {
547 #if defined(Q_OS_WIN32)
548 string.replace('/', '\\');
549 #else
550 string.replace('\\', '/');
551 #endif
552 } else if(flags & Option::FixPathToTargetSeparators) {
553 string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
554 }
555
556 if ((string.startsWith("\"") && string.endsWith("\"")) ||
557 (string.startsWith("\'") && string.endsWith("\'")))
558 string = string.mid(1, string.length()-2);
559
560 //cache
561 //qDebug() << "Fix" << orig_string << "->" << string;
562 cache->insert(cacheKey, string);
563 return string;
564 }
565
debug_msg_internal(int level,const char * fmt,...)566 void debug_msg_internal(int level, const char *fmt, ...)
567 {
568 if(Option::debug_level < level)
569 return;
570 fprintf(stderr, "DEBUG %d: ", level);
571 {
572 va_list ap;
573 va_start(ap, fmt);
574 vfprintf(stderr, fmt, ap);
575 va_end(ap);
576 }
577 fprintf(stderr, "\n");
578 }
579
warn_msg(QMakeWarn type,const char * fmt,...)580 void warn_msg(QMakeWarn type, const char *fmt, ...)
581 {
582 if(!(Option::warn_level & type))
583 return;
584 fprintf(stderr, "WARNING: ");
585 {
586 va_list ap;
587 va_start(ap, fmt);
588 vfprintf(stderr, fmt, ap);
589 va_end(ap);
590 }
591 fprintf(stderr, "\n");
592 }
593
message(int type,const QString & msg,const QString & fileName,int lineNo)594 void EvalHandler::message(int type, const QString &msg, const QString &fileName, int lineNo)
595 {
596 QString pfx;
597 if ((type & QMakeHandler::CategoryMask) == QMakeHandler::WarningMessage) {
598 int code = (type & QMakeHandler::CodeMask);
599 if ((code == QMakeHandler::WarnLanguage && !(Option::warn_level & WarnParser))
600 || (code == QMakeHandler::WarnDeprecated && !(Option::warn_level & WarnDeprecated)))
601 return;
602 pfx = QString::fromLatin1("WARNING: ");
603 }
604 if (lineNo > 0)
605 fprintf(stderr, "%s%s:%d: %s\n", qPrintable(pfx), qPrintable(fileName), lineNo, qPrintable(msg));
606 else if (lineNo)
607 fprintf(stderr, "%s%s: %s\n", qPrintable(pfx), qPrintable(fileName), qPrintable(msg));
608 else
609 fprintf(stderr, "%s%s\n", qPrintable(pfx), qPrintable(msg));
610 }
611
fileMessage(int type,const QString & msg)612 void EvalHandler::fileMessage(int type, const QString &msg)
613 {
614 Q_UNUSED(type)
615 fprintf(stderr, "%s\n", qPrintable(msg));
616 }
617
aboutToEval(ProFile *,ProFile *,EvalFileType)618 void EvalHandler::aboutToEval(ProFile *, ProFile *, EvalFileType)
619 {
620 }
621
doneWithEval(ProFile *)622 void EvalHandler::doneWithEval(ProFile *)
623 {
624 }
625
626 class QMakeCacheClearItem {
627 private:
628 qmakeCacheClearFunc func;
629 void **data;
630 public:
QMakeCacheClearItem(qmakeCacheClearFunc f,void ** d)631 QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
~QMakeCacheClearItem()632 ~QMakeCacheClearItem() {
633 (*func)(*data);
634 *data = nullptr;
635 }
636 };
637 static QList<QMakeCacheClearItem*> cache_items;
638
639 void
qmakeClearCaches()640 qmakeClearCaches()
641 {
642 qDeleteAll(cache_items);
643 cache_items.clear();
644 }
645
646 void
qmakeAddCacheClear(qmakeCacheClearFunc func,void ** data)647 qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
648 {
649 cache_items.append(new QMakeCacheClearItem(func, data));
650 }
651
qmake_libraryInfoFile()652 QString qmake_libraryInfoFile()
653 {
654 if (!Option::globals->qtconf.isEmpty())
655 return Option::globals->qtconf;
656 if (!Option::globals->qmake_abslocation.isEmpty())
657 return QDir(QFileInfo(Option::globals->qmake_abslocation).absolutePath()).filePath("qt.conf");
658 return QString();
659 }
660
qmake_abslocation()661 QString qmake_abslocation()
662 {
663 return Option::globals->qmake_abslocation;
664 }
665
666 QT_END_NAMESPACE
667