Cocoa: Accept mouse clicks that activates windows.
[profile/ivi/qtbase.git] / qmake / option.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the qmake application of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
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 //convenience
55 const char *Option::application_argv0 = 0;
56 QString Option::prf_ext;
57 QString Option::js_ext;
58 QString Option::prl_ext;
59 QString Option::libtool_ext;
60 QString Option::pkgcfg_ext;
61 QString Option::ui_ext;
62 QStringList Option::h_ext;
63 QString Option::cpp_moc_ext;
64 QString Option::h_moc_ext;
65 QStringList Option::cpp_ext;
66 QStringList Option::c_ext;
67 QString Option::obj_ext;
68 QString Option::lex_ext;
69 QString Option::yacc_ext;
70 QString Option::pro_ext;
71 QString Option::mmp_ext;
72 QString Option::dir_sep;
73 QString Option::dirlist_sep;
74 QString Option::h_moc_mod;
75 QString Option::cpp_moc_mod;
76 QString Option::yacc_mod;
77 QString Option::lex_mod;
78 QString Option::sysenv_mod;
79 QString Option::res_ext;
80 char Option::field_sep;
81
82 //mode
83 Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
84
85 //all modes
86 QString Option::qmake_abslocation;
87 int Option::warn_level = WarnLogic | WarnDeprecated;
88 int Option::debug_level = 0;
89 QFile Option::output;
90 QString Option::output_dir;
91 Option::QMAKE_RECURSIVE Option::recursive = Option::QMAKE_RECURSIVE_DEFAULT;
92 QStringList Option::before_user_vars;
93 QStringList Option::after_user_vars;
94 QStringList Option::user_configs;
95 QStringList Option::after_user_configs;
96 QString Option::user_template;
97 QString Option::user_template_prefix;
98 QStringList Option::shellPath;
99 Option::HOST_MODE Option::host_mode = Option::HOST_UNKNOWN_MODE;
100 Option::TARG_MODE Option::target_mode = Option::TARG_UNKNOWN_MODE;
101 bool Option::target_mode_overridden = false;
102
103 //QMAKE_*_PROPERTY stuff
104 QStringList Option::prop::properties;
105
106 //QMAKE_GENERATE_PROJECT stuff
107 bool Option::projfile::do_pwd = true;
108 QStringList Option::projfile::project_dirs;
109
110 //QMAKE_GENERATE_MAKEFILE stuff
111 QString Option::mkfile::qmakespec;
112 int Option::mkfile::cachefile_depth = -1;
113 bool Option::mkfile::do_deps = true;
114 bool Option::mkfile::do_mocs = true;
115 bool Option::mkfile::do_dep_heuristics = true;
116 bool Option::mkfile::do_preprocess = false;
117 bool Option::mkfile::do_stub_makefile = false;
118 bool Option::mkfile::do_cache = true;
119 QString Option::mkfile::cachefile;
120 QStringList Option::mkfile::project_files;
121 QString Option::mkfile::qmakespec_commandline;
122
123 static Option::QMAKE_MODE default_mode(QString progname)
124 {
125     int s = progname.lastIndexOf(QDir::separator());
126     if(s != -1)
127         progname = progname.right(progname.length() - (s + 1));
128     if(progname == "qmakegen")
129         return Option::QMAKE_GENERATE_PROJECT;
130     else if(progname == "qt-config")
131         return Option::QMAKE_QUERY_PROPERTY;
132     return Option::QMAKE_GENERATE_MAKEFILE;
133 }
134
135 static QString detectProjectFile(const QString &path)
136 {
137     QString ret;
138     QDir dir(path);
139     if(dir.exists(dir.dirName() + Option::pro_ext)) {
140         ret = dir.filePath(dir.dirName()) + Option::pro_ext;
141     } else { //last try..
142         QStringList profiles = dir.entryList(QStringList("*" + Option::pro_ext));
143         if(profiles.count() == 1)
144             ret = dir.filePath(profiles.at(0));
145     }
146     return ret;
147 }
148
149 QString project_builtin_regx();
150 bool usage(const char *a0)
151 {
152     fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
153             "\n"
154             "QMake has two modes, one mode for generating project files based on\n"
155             "some heuristics, and the other for generating makefiles. Normally you\n"
156             "shouldn't need to specify a mode, as makefile generation is the default\n"
157             "mode for qmake, but you may use this to test qmake on an existing project\n"
158             "\n"
159             "Mode:\n"
160             "  -project       Put qmake into project file generation mode%s\n"
161             "                 In this mode qmake interprets files as files to\n"
162             "                 be built,\n"
163             "                 defaults to %s\n"
164             "                 Note: The created .pro file probably will \n"
165             "                 need to be edited. For example add the QT variable to \n"
166             "                 specify what modules are required.\n"
167             "  -makefile      Put qmake into makefile generation mode%s\n"
168             "                 In this mode qmake interprets files as project files to\n"
169             "                 be processed, if skipped qmake will try to find a project\n"
170             "                 file in your current working directory\n"
171             "\n"
172             "Warnings Options:\n"
173             "  -Wnone         Turn off all warnings; specific ones may be re-enabled by\n"
174             "                 later -W options\n"
175             "  -Wall          Turn on all warnings\n"
176             "  -Wparser       Turn on parser warnings\n"
177             "  -Wlogic        Turn on logic warnings (on by default)\n"
178             "  -Wdeprecated   Turn on deprecation warnings (on by default)\n"
179             "\n"
180             "Options:\n"
181             "   * You can place any variable assignment in options and it will be     *\n"
182             "   * processed as if it was in [files]. These assignments will be parsed *\n"
183             "   * before [files].                                                     *\n"
184             "  -o file        Write output to file\n"
185             "  -d             Increase debug level\n"
186             "  -t templ       Overrides TEMPLATE as templ\n"
187             "  -tp prefix     Overrides TEMPLATE so that prefix is prefixed into the value\n"
188             "  -help          This help\n"
189             "  -v             Version information\n"
190             "  -after         All variable assignments after this will be\n"
191             "                 parsed after [files]\n"
192             "  -norecursive   Don't do a recursive search\n"
193             "  -recursive     Do a recursive search\n"
194             "  -set <prop> <value> Set persistent property\n"
195             "  -unset <prop>  Unset persistent property\n"
196             "  -query <prop>  Query persistent property. Show all if <prop> is empty.\n"
197             "  -cache file    Use file as cache           [makefile mode only]\n"
198             "  -spec spec     Use spec as QMAKESPEC       [makefile mode only]\n"
199             "  -nocache       Don't use a cache file      [makefile mode only]\n"
200             "  -nodepend      Don't generate dependencies [makefile mode only]\n"
201             "  -nomoc         Don't generate moc targets  [makefile mode only]\n"
202             "  -nopwd         Don't look for files in pwd [project mode only]\n"
203             ,a0,
204             default_mode(a0) == Option::QMAKE_GENERATE_PROJECT  ? " (default)" : "", project_builtin_regx().toLatin1().constData(),
205             default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
206         );
207     return false;
208 }
209
210 int
211 Option::parseCommandLine(int argc, char **argv, int skip)
212 {
213     bool before = true;
214     for(int x = skip; x < argc; x++) {
215         if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */
216             QString opt = argv[x] + 1;
217
218             //first param is a mode, or we default
219             if(x == 1) {
220                 bool specified = true;
221                 if(opt == "project") {
222                     Option::recursive = Option::QMAKE_RECURSIVE_YES;
223                     Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
224                 } else if(opt == "prl") {
225                     Option::mkfile::do_deps = false;
226                     Option::mkfile::do_mocs = false;
227                     Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
228                 } else if(opt == "set") {
229                     Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
230                 } else if(opt == "unset") {
231                     Option::qmake_mode = Option::QMAKE_UNSET_PROPERTY;
232                 } else if(opt == "query") {
233                     Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
234                 } else if(opt == "makefile") {
235                     Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
236                 } else {
237                     specified = false;
238                 }
239                 if(specified)
240                     continue;
241             }
242             //all modes
243             if(opt == "o" || opt == "output") {
244                 Option::output.setFileName(argv[++x]);
245             } else if(opt == "after") {
246                 before = false;
247             } else if(opt == "t" || opt == "template") {
248                 Option::user_template = argv[++x];
249             } else if(opt == "tp" || opt == "template_prefix") {
250                 Option::user_template_prefix = argv[++x];
251             } else if(opt == "macx") {
252                 fprintf(stderr, "-macx is deprecated.\n");
253                 Option::host_mode = HOST_MACX_MODE;
254                 Option::target_mode = TARG_MACX_MODE;
255                 Option::target_mode_overridden = true;
256             } else if(opt == "unix") {
257                 fprintf(stderr, "-unix is deprecated.\n");
258                 Option::host_mode = HOST_UNIX_MODE;
259                 Option::target_mode = TARG_UNIX_MODE;
260                 Option::target_mode_overridden = true;
261             } else if(opt == "win32") {
262                 fprintf(stderr, "-win32 is deprecated.\n");
263                 Option::host_mode = HOST_WIN_MODE;
264                 Option::target_mode = TARG_WIN_MODE;
265                 Option::target_mode_overridden = true;
266             } else if(opt == "integrity") {
267                 Option::target_mode = TARG_INTEGRITY_MODE;
268             } else if(opt == "d") {
269                 Option::debug_level++;
270             } else if(opt == "version" || opt == "v" || opt == "-version") {
271                 fprintf(stdout,
272                         "QMake version %s\n"
273                         "Using Qt version %s in %s\n",
274                         qmake_version(), QT_VERSION_STR,
275                         QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
276 #ifdef QMAKE_OPENSOURCE_VERSION
277                 fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
278 #endif
279                 return Option::QMAKE_CMDLINE_BAIL;
280             } else if(opt == "h" || opt == "help") {
281                 return Option::QMAKE_CMDLINE_SHOW_USAGE;
282             } else if(opt == "Wall") {
283                 Option::warn_level |= WarnAll;
284             } else if(opt == "Wparser") {
285                 Option::warn_level |= WarnParser;
286             } else if(opt == "Wlogic") {
287                 Option::warn_level |= WarnLogic;
288             } else if(opt == "Wdeprecated") {
289                 Option::warn_level |= WarnDeprecated;
290             } else if(opt == "Wnone") {
291                 Option::warn_level = WarnNone;
292             } else if(opt == "r" || opt == "recursive") {
293                 Option::recursive = Option::QMAKE_RECURSIVE_YES;
294             } else if(opt == "nr" || opt == "norecursive") {
295                 Option::recursive = Option::QMAKE_RECURSIVE_NO;
296             } else if(opt == "config") {
297                 Option::user_configs += argv[++x];
298             } else {
299                 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
300                    Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
301                     if(opt == "nodepend" || opt == "nodepends") {
302                         Option::mkfile::do_deps = false;
303                     } else if(opt == "nomoc") {
304                         Option::mkfile::do_mocs = false;
305                     } else if(opt == "nocache") {
306                         Option::mkfile::do_cache = false;
307                     } else if(opt == "createstub") {
308                         Option::mkfile::do_stub_makefile = true;
309                     } else if(opt == "nodependheuristics") {
310                         Option::mkfile::do_dep_heuristics = false;
311                     } else if(opt == "E") {
312                         fprintf(stderr, "-E is deprecated. Use -d instead.\n");
313                         Option::mkfile::do_preprocess = true;
314                     } else if(opt == "cache") {
315                         Option::mkfile::cachefile = argv[++x];
316                     } else if(opt == "platform" || opt == "spec") {
317                         Option::mkfile::qmakespec = argv[++x];
318                         Option::mkfile::qmakespec_commandline = argv[x];
319                     } else {
320                         fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
321                         return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
322                     }
323                 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
324                     if(opt == "nopwd") {
325                         Option::projfile::do_pwd = false;
326                     } else {
327                         fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
328                         return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
329                     }
330                 }
331             }
332         } else {
333             QString arg = argv[x];
334             if(arg.indexOf('=') != -1) {
335                 if(before)
336                     Option::before_user_vars.append(arg);
337                 else
338                     Option::after_user_vars.append(arg);
339             } else {
340                 bool handled = true;
341                 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
342                     Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
343                     Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) {
344                     Option::prop::properties.append(arg);
345                 } else {
346                     QFileInfo fi(arg);
347                     if(!fi.makeAbsolute()) //strange
348                         arg = fi.filePath();
349                     if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
350                        Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
351                         if(fi.isDir()) {
352                             QString proj = detectProjectFile(arg);
353                             if (!proj.isNull())
354                                 arg = proj;
355                         }
356                         Option::mkfile::project_files.append(arg);
357                     } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
358                         Option::projfile::project_dirs.append(arg);
359                     } else {
360                         handled = false;
361                     }
362                 }
363                 if(!handled) {
364                     return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
365                 }
366             }
367         }
368     }
369
370     return Option::QMAKE_CMDLINE_SUCCESS;
371 }
372
373 #ifdef Q_OS_WIN
374 static QStringList detectShellPath()
375 {
376     QStringList paths;
377     QString path = qgetenv("PATH");
378     QStringList pathlist = path.toLower().split(";");
379     for (int i = 0; i < pathlist.count(); i++) {
380         QString maybeSh = pathlist.at(i) + "/sh.exe";
381         if (QFile::exists(maybeSh)) {
382             paths.append(maybeSh);
383         }
384     }
385     return paths;
386 }
387 #endif
388
389 int
390 Option::init(int argc, char **argv)
391 {
392     Option::application_argv0 = 0;
393     Option::cpp_moc_mod = "";
394     Option::h_moc_mod = "moc_";
395     Option::lex_mod = "_lex";
396     Option::yacc_mod = "_yacc";
397     Option::prl_ext = ".prl";
398     Option::libtool_ext = ".la";
399     Option::pkgcfg_ext = ".pc";
400     Option::prf_ext = ".prf";
401     Option::js_ext = ".js";
402     Option::ui_ext = ".ui";
403     Option::h_ext << ".h" << ".hpp" << ".hh" << ".hxx";
404     Option::c_ext << ".c";
405 #ifndef Q_OS_WIN
406     Option::h_ext << ".H";
407 #endif
408     Option::cpp_moc_ext = ".moc";
409     Option::h_moc_ext = ".cpp";
410     Option::cpp_ext << ".cpp" << ".cc" << ".cxx";
411 #ifndef Q_OS_WIN
412     Option::cpp_ext << ".C";
413 #endif
414     Option::lex_ext = ".l";
415     Option::yacc_ext = ".y";
416     Option::pro_ext = ".pro";
417     Option::mmp_ext = ".mmp";
418 #ifdef Q_OS_WIN
419     Option::dirlist_sep = ";";
420     Option::shellPath = detectShellPath();
421     Option::res_ext = ".res";
422 #else
423     Option::dirlist_sep = ":";
424     Option::shellPath = QStringList("sh");
425 #endif
426     Option::sysenv_mod = "QMAKE_ENV_";
427     Option::field_sep = ' ';
428
429     if(argc && argv) {
430         Option::application_argv0 = argv[0];
431         QString argv0 = argv[0];
432         if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
433             Option::qmake_mode = default_mode(argv0);
434         if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
435             Option::qmake_abslocation = argv0;
436         } else if (argv0.contains(QLatin1Char('/'))
437 #ifdef Q_OS_WIN
438                    || argv0.contains(QLatin1Char('\\'))
439 #endif
440             ) { //relative PWD
441             Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
442         } else { //in the PATH
443             QByteArray pEnv = qgetenv("PATH");
444             QDir currentDir = QDir::current();
445 #ifdef Q_OS_WIN
446             QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
447 #else
448             QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
449 #endif
450             for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
451                 if ((*p).isEmpty())
452                     continue;
453                 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
454 #ifdef Q_OS_WIN
455                 candidate += ".exe";
456 #endif
457                 if (QFile::exists(candidate)) {
458                     Option::qmake_abslocation = candidate;
459                     break;
460                 }
461             }
462         }
463         if(!Option::qmake_abslocation.isNull())
464             Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
465     } else {
466         Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
467     }
468
469     const QByteArray envflags = qgetenv("QMAKEFLAGS");
470     if (!envflags.isNull()) {
471         int env_argc = 0, env_size = 0, currlen=0;
472         char quote = 0, **env_argv = NULL;
473         for (int i = 0; i < envflags.size(); ++i) {
474             if (!quote && (envflags.at(i) == '\'' || envflags.at(i) == '"')) {
475                 quote = envflags.at(i);
476             } else if (envflags.at(i) == quote) {
477                 quote = 0;
478             } else if (!quote && envflags.at(i) == ' ') {
479                 if (currlen && env_argv && env_argv[env_argc]) {
480                     env_argv[env_argc][currlen] = '\0';
481                     currlen = 0;
482                     env_argc++;
483                 }
484             } else {
485                 if(!env_argv || env_argc > env_size) {
486                     env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
487                     for(int i2 = env_argc; i2 < env_size; i2++)
488                         env_argv[i2] = NULL;
489                 }
490                 if(!env_argv[env_argc]) {
491                     currlen = 0;
492                     env_argv[env_argc] = (char*)malloc(255);
493                 }
494                 if(currlen < 255)
495                     env_argv[env_argc][currlen++] = envflags.at(i);
496             }
497         }
498         if(env_argv) {
499             if(env_argv[env_argc]) {
500                 env_argv[env_argc][currlen] = '\0';
501                 currlen = 0;
502                 env_argc++;
503             }
504             parseCommandLine(env_argc, env_argv);
505             for(int i2 = 0; i2 < env_size; i2++) {
506                 if(env_argv[i2])
507                     free(env_argv[i2]);
508             }
509             free(env_argv);
510         }
511     }
512     if(argc && argv) {
513         int ret = parseCommandLine(argc, argv, 1);
514         if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
515             if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
516                 usage(argv[0]);
517             return ret;
518             //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
519         }
520     }
521
522     //last chance for defaults
523     if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
524         Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
525         if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
526             Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
527
528         //try REALLY hard to do it for them, lazy..
529         if(Option::mkfile::project_files.isEmpty()) {
530             QString proj = detectProjectFile(qmake_getpwd());
531             if(!proj.isNull())
532                 Option::mkfile::project_files.append(proj);
533 #ifndef QT_BUILD_QMAKE_LIBRARY
534             if(Option::mkfile::project_files.isEmpty()) {
535                 usage(argv[0]);
536                 return Option::QMAKE_CMDLINE_ERROR;
537             }
538 #endif
539         }
540     } else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
541 #if defined(Q_OS_MAC)
542         Option::host_mode = Option::HOST_MACX_MODE;
543         Option::target_mode = Option::TARG_MACX_MODE;
544 #elif defined(Q_OS_UNIX)
545         Option::host_mode = Option::HOST_UNIX_MODE;
546         Option::target_mode = Option::TARG_UNIX_MODE;
547 #else
548         Option::host_mode = Option::HOST_WIN_MODE;
549         Option::target_mode = Option::TARG_WIN_MODE;
550 #endif
551     }
552
553     //defaults for globals
554     if (Option::host_mode != Option::HOST_UNKNOWN_MODE)
555         applyHostMode();
556     return QMAKE_CMDLINE_SUCCESS;
557 }
558
559 void Option::applyHostMode()
560 {
561    if (Option::host_mode == Option::HOST_WIN_MODE) {
562        Option::dir_sep = "\\";
563        Option::obj_ext = ".obj";
564    } else {
565        Option::dir_sep = "/";
566        Option::obj_ext = ".o";
567    }
568 }
569
570 bool Option::postProcessProject(QMakeProject *project)
571 {
572     Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
573     if(cpp_ext.isEmpty())
574         cpp_ext << ".cpp"; //something must be there
575     Option::h_ext = project->variables()["QMAKE_EXT_H"];
576     if(h_ext.isEmpty())
577         h_ext << ".h";
578     Option::c_ext = project->variables()["QMAKE_EXT_C"];
579     if(c_ext.isEmpty())
580         c_ext << ".c"; //something must be there
581
582     if(!project->isEmpty("QMAKE_EXT_RES"))
583         Option::res_ext = project->first("QMAKE_EXT_RES");
584     if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
585         Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
586     if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
587         Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
588     if(!project->isEmpty("QMAKE_EXT_PRL"))
589         Option::prl_ext = project->first("QMAKE_EXT_PRL");
590     if(!project->isEmpty("QMAKE_EXT_PRF"))
591         Option::prf_ext = project->first("QMAKE_EXT_PRF");
592     if(!project->isEmpty("QMAKE_EXT_JS"))
593         Option::prf_ext = project->first("QMAKE_EXT_JS");
594     if(!project->isEmpty("QMAKE_EXT_UI"))
595         Option::ui_ext = project->first("QMAKE_EXT_UI");
596     if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
597         Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
598     if(!project->isEmpty("QMAKE_EXT_H_MOC"))
599         Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
600     if(!project->isEmpty("QMAKE_EXT_LEX"))
601         Option::lex_ext = project->first("QMAKE_EXT_LEX");
602     if(!project->isEmpty("QMAKE_EXT_YACC"))
603         Option::yacc_ext = project->first("QMAKE_EXT_YACC");
604     if(!project->isEmpty("QMAKE_EXT_OBJ"))
605         Option::obj_ext = project->first("QMAKE_EXT_OBJ");
606     if(!project->isEmpty("QMAKE_H_MOD_MOC"))
607         Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
608     if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
609         Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
610     if(!project->isEmpty("QMAKE_MOD_LEX"))
611         Option::lex_mod = project->first("QMAKE_MOD_LEX");
612     if(!project->isEmpty("QMAKE_MOD_YACC"))
613         Option::yacc_mod = project->first("QMAKE_MOD_YACC");
614     if(!project->isEmpty("QMAKE_DIR_SEP"))
615         Option::dir_sep = project->first("QMAKE_DIR_SEP");
616     if(!project->isEmpty("QMAKE_DIRLIST_SEP"))
617         Option::dirlist_sep = project->first("QMAKE_DIRLIST_SEP");
618     if(!project->isEmpty("QMAKE_MOD_SYSTEM_ENV"))
619         Option::sysenv_mod = project->first("QMAKE_MOD_SYSTEM_ENV");
620     return true;
621 }
622
623 QString
624 Option::fixString(QString string, uchar flags)
625 {
626     //const QString orig_string = string;
627     static QHash<FixStringCacheKey, QString> *cache = 0;
628     if(!cache) {
629         cache = new QHash<FixStringCacheKey, QString>;
630         qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache);
631     }
632     FixStringCacheKey cacheKey(string, flags);
633
634     QHash<FixStringCacheKey, QString>::const_iterator it = cache->constFind(cacheKey);
635
636     if (it != cache->constEnd()) {
637         //qDebug() << "Fix (cached) " << orig_string << "->" << it.value();
638         return it.value();
639     }
640
641     //fix the environment variables
642     if(flags & Option::FixEnvVars) {
643         int rep;
644         static QRegExp reg_var("\\$\\(.*\\)");
645         reg_var.setMinimal(true);
646         while((rep = reg_var.indexIn(string)) != -1)
647             string.replace(rep, reg_var.matchedLength(),
648                            QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
649     }
650
651     //canonicalize it (and treat as a path)
652     if(flags & Option::FixPathCanonicalize) {
653 #if 0
654         string = QFileInfo(string).canonicalFilePath();
655 #endif
656         string = QDir::cleanPath(string);
657     }
658
659     if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
660         string[0] = string[0].toLower();
661
662     //fix separators
663     Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
664     if(flags & Option::FixPathToLocalSeparators) {
665 #if defined(Q_OS_WIN32)
666         string = string.replace('/', '\\');
667 #else
668         string = string.replace('\\', '/');
669 #endif
670     } else if(flags & Option::FixPathToTargetSeparators) {
671         string = string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
672     }
673
674     if ((string.startsWith("\"") && string.endsWith("\"")) ||
675         (string.startsWith("\'") && string.endsWith("\'")))
676         string = string.mid(1, string.length()-2);
677
678     //cache
679     //qDebug() << "Fix" << orig_string << "->" << string;
680     cache->insert(cacheKey, string);
681     return string;
682 }
683
684 const char *qmake_version()
685 {
686     static char *ret = NULL;
687     if(ret)
688         return ret;
689     ret = (char *)malloc(15);
690     qmakeAddCacheClear(qmakeFreeCacheClear, (void**)&ret);
691 #if defined(_MSC_VER) && _MSC_VER >= 1400
692     sprintf_s(ret, 15, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
693 #else
694     sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
695 #endif
696     return ret;
697 }
698
699 void debug_msg_internal(int level, const char *fmt, ...)
700 {
701     if(Option::debug_level < level)
702         return;
703     fprintf(stderr, "DEBUG %d: ", level);
704     {
705         va_list ap;
706         va_start(ap, fmt);
707         vfprintf(stderr, fmt, ap);
708         va_end(ap);
709     }
710     fprintf(stderr, "\n");
711 }
712
713 void warn_msg(QMakeWarn type, const char *fmt, ...)
714 {
715     if(!(Option::warn_level & type))
716         return;
717     fprintf(stderr, "WARNING: ");
718     {
719         va_list ap;
720         va_start(ap, fmt);
721         vfprintf(stderr, fmt, ap);
722         va_end(ap);
723     }
724     fprintf(stderr, "\n");
725 }
726
727 class QMakeCacheClearItem {
728 private:
729     qmakeCacheClearFunc func;
730     void **data;
731 public:
732     QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
733     ~QMakeCacheClearItem() {
734         (*func)(*data);
735         *data = 0;
736     }
737 };
738 static QList<QMakeCacheClearItem*> cache_items;
739
740 void
741 qmakeClearCaches()
742 {
743     qDeleteAll(cache_items);
744     cache_items.clear();
745 }
746
747 void
748 qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
749 {
750     cache_items.append(new QMakeCacheClearItem(func, data));
751 }
752
753 QString qmake_libraryInfoFile()
754 {
755     if(!Option::qmake_abslocation.isEmpty())
756         return QDir(QFileInfo(Option::qmake_abslocation).absolutePath()).filePath("qt.conf");
757     return QString();
758 }
759
760 QT_END_NAMESPACE