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