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